1.项目背景 这里简单介绍一下项目需求背景,之前公司的项目基于EF++Repository+UnitOfWork的框架设计的,其中涉及到的技术有RabbitMq消息队列,Autofac依赖注入等常用的.net插件。由于公司的发展,业务不断更新,变得复杂起来,对于数据的实时性、存储容量要求也提高了一个新的高度。数据库上下文DbContext设计的是单例模式,基本上告别了多线程高并发的数据读写能力,看了园子里很多大神的博客,均为找到适合自己当前需求的DbContext的管理方式。总结目前主要的管理方式: 1)DbContext单例模式(长连接)。即公司之前的设计。很明显,这种设计方式无法支持多线程同步数据操作。报各种错误,最常见的,比如:集合已修改,无法进行枚举操作。—弃用 2)Using模式(短连接)。这种模式适合一些对于外键,导航属性不经常使用的场合,由于导航属性是放在上下文缓存中的,一旦上下文释放掉,导航属性就为null。当然,也尝试了其他大神的做法,比如,在上下文释放之前转换为 ToList或者使用饥饿加载的方式(ps:这种方式很不灵活,你总不可能遇到一个类类型就去利用反射加载找到它具有的导航属性吧或者直接InCluding),这些方法依旧没有办法解决目前的困境。也尝试这直接赋值给一个定义的同类 型的变量,但是对于这种带导航的导航的复杂类的深拷贝,没有找到合适的路子,有知道的可以告诉我,非常感谢! 以上两种方式及网上寻找的其他方式都没有解决我的问题。这里先上一下之前的Repository:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
1 using System.Data.Entity; 2 using System.Data.Entity.Validation; 3 4 namespace MM.Data.Library.Entityframework 5 { 6 public class EntityFrameworkRepositoryContext : RepositoryContext, IEntityFrameworkRepositoryContext 7 { 8 protected DbContext container; 9 10 public EntityFrameworkRepositoryContext(DbContext container) 11 { 12 this.container = container; 13 } 14 15 public override void RegisterNew<TAggregateRoot>(TAggregateRoot obj) 16 { 17 this.container.Set<TAggregateRoot>().Add(obj); 18 this.IsCommit = false; 19 } 20 21 public override void RegisterModified<TAggregateRoot>(TAggregateRoot obj) 22 { 23 if (this.container.Entry<TAggregateRoot>(obj).State == EntityState.Detached) 24 { 25 this.container.Set<TAggregateRoot>().Attach(obj); 26 } 27 this.container.Entry<TAggregateRoot>(obj).State = EntityState.Modified; 28 this.IsCommit = false; 29 } 30 31 public override void RegisterDeleted<TAggregateRoot>(TAggregateRoot obj) 32 { 33 this.container.Set<TAggregateRoot>().Remove(obj); 34 this.IsCommit = false; 35 } 36 37 public override void Rollback() 38 { 39 this.IsCommit = false; 40 } 41 42 protected override void DoCommit() 43 { 44 if (!IsCommit) 45 { 46 //var count = container.SaveChanges(); 47 //IsCommit = true; 48 try 49 { 50 var count = container.SaveChanges(); 51 IsCommit = true; 52 } 53 catch (DbEntityValidationException dbEx) 54 { 55 foreach (var validationErrors in dbEx.EntityValidationErrors) 56 { 57 foreach (var validationError in validationErrors.ValidationErrors) 58 { 59 } 60 } 61 IsCommit = false; 62 } 63 } 64 } 65 66 public System.Data.Entity.DbContext DbContext 67 { 68 get { return container; } 69 } 70 71 public override void Dispose() 72 { 73 if (container != null) 74 container.Dispose(); 75 } 76 } 77 } |
View Code 2.设计思路及方法 从上下文的单例模式来看,所要解决的问题无非就是在多线程对数据库写操作上面。只要在这上面做手脚,问题应该就能引刃而解。我的想法是将所有的要修改的数据分别放入UpdateList,InsertList,DeleteList三个集合中去,然后提交到数据库保存。至于DbContext的管理,通过一个数据库工厂获取,保证每一个数据库的连接都是唯一的,不重复的(防止发生类似这种错误:正在创建模型,此时不可使用上下文。),用的时候直接去Factory拿。等到数据库提交成功后,清空集合数据。看起来,实现起来很容易,但是因为还涉及到其他技术,比如Redis。所以实现过程费劲。也许我的能力还差很多。总之,废话不多说,直接上部分实现代码: 数据库上下文建立工厂:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
1 /// <summary> 2 /// 数据库建立工厂 3 /// Modify By: 4 /// Modify Date: 5 /// Modify Reason: 6 /// </summary> 7 public sealed class DbFactory 8 { 9 public static IDbContext GetCurrentDbContext(string connectstring,string threadName) 10 { 11 lock (threadName) 12 { 13 //CallContext:是线程内部唯一的独用的数据槽(一块内存空间) 14 //传递Context进去获取实例的信息,在这里进行强制转换。 15 var Context = CallContext.GetData("Context") as IDbContext; 16 17 if (Context == null) //线程在内存中没有此上下文 18 { 19 var Scope = UnitoonIotContainer.Container.BeginLifetimeScope(); 20 //如果不存在上下文 创建一个(自定义)EF上下文 并且放在数据内存中去 21 Context = Scope.Resolve<IDbContext>(new NamedParameter("connectionString", connectstring)); 22 CallContext.SetData("Context", Context); 23 } 24 else 25 { 26 27 if (!Context.ConnectionString.Equals(connectstring)) 28 { 29 var Scope = UnitoonIotContainer.Container.BeginLifetimeScope(); 30 //如果不存在上下文 创建一个(自定义)EF上下文 并且放在数据内存中去 31 Context = Scope.Resolve<IDbContext>(new NamedParameter("connectionString", connectstring)); 32 CallContext.SetData("Context", Context); 33 } 34 } 35 return Context; 36 } 37 } 38 39 } |
View Code Repository:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
1 public class RepositoryBase<T, TContext> : IRepositoryBase<T> where T : BaseEntity 2 3 where TContext : ContextBase, IDbContext, IDisposable, new() 4 { 5 public List<T> InsertList { get; set; } 6 public List<T> DeleteList { get; set; } 7 public List<T> UpdateList { get; set; } 8 9 #region field 10 11 protected readonly string Connectstring; 12 ///// <summary> 13 ///// </summary> 14 //protected static IDbContext Context; 15 protected IDbContext dbContext; 16 private static readonly ILifetimeScope Scope; 17 public static int xcount = 0; 18 /////// <summary> 19 /////// </summary> 20 //protected readonly DbSet<T> Dbset; 21 22 #endregion 23 24 #region ctor 25 26 static RepositoryBase() 27 { 28 Scope = UnitoonIotContainer.Container.BeginLifetimeScope(); 29 } 30 31 /// <summary> 32 /// 使用默认连接字符串name=connName 33 /// </summary> 34 public RepositoryBase() : this("") 35 { 36 } 37 38 /// <summary> 39 /// 构造函数 40 /// </summary> 41 /// <param name="connectionString">连接字符串</param> 42 public RepositoryBase(string connectionString) 43 { 44 InsertList = new List<T>(); 45 DeleteList = new List<T>(); 46 UpdateList = new List<T>(); 47 48 49 //*****做以下调整,初始化,建立所有数据库连接,保持长连接状态,在用的时候去判断使用连接 50 51 52 //todo 待处理 53 54 55 if (string.IsNullOrWhiteSpace(connectionString)) 56 { 57 var name = DataBase.GetConnectionString(Activator.CreateInstance<T>().DbType); 58 //Context= ContextHelper.GetDbContext(Activator.CreateInstance<T>().DbType); 59 connectionString = name; 60 } 61 Connectstring = connectionString; 62 63 // Context = Scope.Resolve<IDbContext>(new NamedParameter("connectionString", Connectstring)); 64 65 //Context = new TContext { ConnectionString = connectionString }; 66 67 68 // Dbset = Context.Set<T>(); 69 70 //var loggerFactory = ((DbContext)Context).GetService<ILoggerFactory>(); 71 //loggerFactory.AddProvider(new DbLoggerProvider(Console.WriteLine)); 72 //loggerFactory.AddConsole(minLevel: LogLevel.Warning); 73 } 74 75 //public RepositoryBase(TContext context) 76 //{ 77 // Context = context; 78 // Dbset = context.Set<T>(); 79 //} 80 81 #endregion 82 83 #region Method 84 85 //public virtual IDbContext GetDbContext(ILifetimeScope scope) 86 //{ 87 88 //} 89 90 #region Check Model 91 92 /// <summary> 93 /// 校正Model 94 /// </summary> 95 protected virtual void ValidModel() 96 { 97 } 98 99 #endregion 100 101 #region Update 102 103 public virtual void Update(T entity) 104 { 105 Check.NotNull(entity, "entity"); 106 UpdateList.Add(entity); 107 //context.Set<T>().Update(entity); 108 } 109 110 public virtual void Update(IEnumerable<T> entities) 111 { 112 Check.NotNull(entities, "entities"); 113 UpdateList.AddRange(entities); 114 } 115 116 #endregion 117 118 #region PageList 119 120 public virtual IEnumerable<T> GetPageList(Expression<Func<T, bool>> where, Expression<Func<T, object>> orderBy, 121 int pageIndex, int pageSize) 122 { 123 //todo 124 } 125 126 #endregion 127 128 #region Insert 129 130 public virtual void Add(T entity) 131 { 132 Check.NotNull(entity, "entity"); 133 //排除已经存在的项(对于多线程没有任何用处) 134 if (!InsertList.Exists(e => e.Equals(entity))) 135 { 136 InsertList.Add(entity); 137 } 138 139 } 140 141 public virtual void Add(IEnumerable<T> entities) 142 { 143 Check.NotNull(entities, "entities"); 144 InsertList.AddRange(entities); 145 } 146 147 public void BulkInsert(IEnumerable<T> entities) 148 { 149 Check.NotNull(entities, "entities"); 150 InsertList.AddRange(entities); 151 } 152 153 #endregion 154 155 #region Delete 156 157 public virtual void Delete(int id) 158 { 159 var entity = GetById(id); 160 Delete(entity); 161 // throw new NotImplementedException("Delete(int id)"); 162 } 163 164 public virtual void Delete(string id) 165 { 166 throw new NotImplementedException("Delete(string id)"); 167 } 168 169 public virtual void Delete(T entity) 170 { 171 Check.NotNull(entity, "entity"); 172 DeleteList.Add(entity); 173 } 174 175 public virtual void Delete(IEnumerable<T> entities) 176 { 177 Check.NotNull(entities, "entities"); 178 foreach (var x1 in DeleteList) 179 { 180 DeleteList.Add(x1); 181 } 182 } 183 184 public virtual void Delete(Expression<Func<T, bool>> where) 185 { 186 var list = DeleteList.Where(where.Compile()); 187 Delete(list); 188 } 189 190 #endregion 191 192 #region Commit 193 194 public int Commit() 195 { 196 ValidModel(); 197 //var x = Activator.CreateInstance<T>(); 198 //Context = ContextHelper.GetDbContext(x.DbType); 199 //using (var scope = UnitoonIotContainer.Container.BeginLifetimeScope()) 200 //{ 201 // var context = scope.Resolve<IDbContext>(new NamedParameter("connectionString", Connectstring)); 202 203 //var loggerFactory = Activator.CreateInstance<ILoggerFactory>();// ((DbContext)context).GetService<ILoggerFactory>(); 204 //loggerFactory.AddProvider(new DbLoggerProvider(Console.WriteLine)); 205 dbContext = DbFactory.GetCurrentDbContext(Connectstring, Thread.CurrentThread.Name); 206 var dbset = dbContext.Set<T>(); 207 if (InsertList != null && InsertList.Any()) 208 { 209 List<T> InsertNewList = InsertList.Distinct(new PropertyComparer<T>("Id")).ToList();//按照特定规则排除重复项 210 dbset.AddRange(InsertNewList); 211 } 212 213 if (DeleteList != null && DeleteList.Any()) 214 DeleteList.ForEach(t => 215 { 216 // Context.Entry(t).State = EntityState.Detached;//将之前上下文跟踪的状态丢弃 217 //dbContext.Entry(t).State = EntityState.Detached;//将之前上下文跟踪的状态丢弃 218 dbset.Attach(t); 219 dbset.Remove(t); 220 }); 221 if (UpdateList != null && UpdateList.Any()) 222 { 223 List<T> UpdateNewList = UpdateList.Distinct(new PropertyComparer<T>("Id")).ToList();//按照特定规则排除重复项 224 UpdateNewList.ForEach(t => 225 { 226 //Context.Entry(t).State = EntityState.Detached;//将之前上下文跟踪的状态丢弃 227 // dbContext.Entry(t).State = EntityState.Detached;//将之前上下文跟踪的状态丢弃 228 dbContext.Entry(t).State = EntityState.Modified; 229 });//.UpdateRange(UpdateNewList); 230 } 231 var result = 0; 232 try 233 { 234 result = dbContext.SaveChanges(); 235 } 236 catch (Exception ex) 237 { 238 239 // throw; 240 } 241 242 if (InsertList != null && InsertList.Any()) 243 InsertList.Clear(); 244 if (DeleteList != null && DeleteList.Any()) 245 DeleteList.Clear(); 246 if (UpdateList != null && UpdateList.Any()) 247 UpdateList.Clear(); 248 return result; 249 //} 250 } 251 252 public async Task<int> CommitAsync() 253 { 254 ValidModel(); 255 //todo 256 257 } 258 259 #endregion 260 261 #region Query 262 public IQueryable<T> Get() 263 { 264 return GetAll().AsQueryable(); 265 } 266 //public virtual T Get(Expression<Func<T, bool>> @where) 267 //{ 268 // using (var scope = UnitoonIotContainer.Container.BeginLifetimeScope()) 269 // { 270 271 // var context = scope.Resolve<IDbContext>(new NamedParameter("connectionString", Connectstring)); 272 // var dbset = context.Set<T>(); 273 // return dbset.FirstOrDefault(where); 274 // } 275 //} 276 277 public virtual async Task<T> GetAsync(Expression<Func<T, bool>> @where) 278 { 279 //todo 280 } 281 282 public virtual T GetById(int id) 283 { 284 throw new NotImplementedException("GetById(int id)"); 285 } 286 287 public virtual async Task<T> GetByIdAsync(int id) 288 { 289 throw new NotImplementedException("GetById(int id)"); 290 } 291 292 public virtual T GetById(string id) 293 { 294 throw new NotImplementedException("GetById(int id)"); 295 } 296 297 public virtual async Task<T> GetByIdAsync(string id) 298 { 299 throw new NotImplementedException("GetById(int id)"); 300 } 301 302 public virtual T Get(Expression<Func<T, bool>> @where)//, params string[] includeProperties 303 { 304 //var scope = UnitoonIotContainer.Container.BeginLifetimeScope(); 305 //{ 306 // var context = scope.Resolve<IDbContext>(new NamedParameter("connectionString", Connectstring)); 307 //Thread.Sleep(50); 308 //lock (Context) 309 { 310 dbContext= DbFactory.GetCurrentDbContext(Connectstring, Thread.CurrentThread.Name); 311 var dbset = dbContext.Set<T>().Where(e => !e.IsDeleted).AsQueryable(); 312 var entity = dbset.FirstOrDefault(where); 313 //test 314 // Context.Entry(entity).State = EntityState.Detached;//将之前上下文跟踪的状态丢弃 315 return entity; 316 } 317 318 319 //} 320 } 321 322 public virtual IEnumerable<T> GetAll() 323 { 324 //Thread.Sleep(50); 325 //lock (Context) 326 { 327 dbContext = DbFactory.GetCurrentDbContext(Connectstring, Thread.CurrentThread.Name); 328 var dbset = dbContext.Set<T>().Where(e => !e.IsDeleted); 329 //test 330 //dbset.ToList().ForEach(t => 331 //{ 332 // Context.Entry(t).State = EntityState.Detached;//将之前上下文跟踪的状态丢弃 333 //}); 334 335 return dbset; 336 } 337 338 339 340 341 //var scope = UnitoonIotContainer.Container.BeginLifetimeScope(); 342 343 // var context = scope.Resolve<IDbContext>(new NamedParameter("connectionString", Connectstring)); 344 345 } 346 347 public async virtual Task<IEnumerable<T>> GetAllAsync() 348 { 349 //todo 350 } 351 352 public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where) 353 { 354 //using (var scope = UnitoonIotContainer.Container.BeginLifetimeScope()) 355 //{ 356 // var context = scope.Resolve<IDbContext>(new NamedParameter("connectionString", Connectstring)); 357 358 // var dbset = context.Set<T>(); 359 //Thread.Sleep(50); 360 //lock (Context) 361 { 362 dbContext = DbFactory.GetCurrentDbContext(Connectstring, Thread.CurrentThread.Name); 363 var dbset = dbContext.Set<T>().Where(e => !e.IsDeleted); 364 //test 365 //dbset.ToList().ForEach(t => 366 //{ 367 // Context.Entry(t).State = EntityState.Detached;//将之前上下文跟踪的状态丢弃 368 //}); 369 return dbset.Where(@where).ToList(); 370 } 371 372 //} 373 } 374 375 public virtual async Task<IEnumerable<T>> GetManyAsync(Expression<Func<T, bool>> where) 376 { 377 //todo 378 } 379 380 public virtual IEnumerable<T> IncludeSubSets(params Expression<Func<T, object>>[] includeProperties) 381 { 382 //todo 383 } 384 385 #region navigation 386 /// <summary> 387 /// 加载导航 388 /// </summary> 389 /// <param name="where"></param> 390 /// <param name="includeProperties"></param> 391 /// <returns></returns> 392 //public virtual T Get(Expression<Func<T, bool>> @where, params Expression<Func<T, object>>[] includeProperties) 393 //{ 394 // using (var scope = UnitoonIotContainer.Container.BeginLifetimeScope()) 395 // { 396 397 // var context = scope.Resolve<IDbContext>(new NamedParameter("connectionString", Connectstring)); 398 // var dbset = context.Set<T>(); 399 // var query = includeProperties.Aggregate<Expression<Func<T, object>>, IQueryable<T>>(dbset, 400 // (current, includeProperty) => current.Include(includeProperty)); 401 // return query.FirstOrDefault(where); 402 // } 403 //} 404 405 //public virtual T Get(Expression<Func<T, bool>> @where)//, params string[] includeProperties 406 //{ 407 // //反射获取导航 408 // var includeProperties = 409 // Activator.CreateInstance<T>().GetType().GetProperties().Where(p => p.GetMethod.IsVirtual).Select(e => e.Name).ToArray(); 410 411 //todo 412 //} 413 #endregion 414 public List<TDynamicEntity> GetDynamic<TTable, TDynamicEntity>(Expression<Func<TTable, object>> selector, 415 Func<object, TDynamicEntity> maker) where TTable : class 416 { 417 //todo 418 } 419 420 public List<TDynamicEntity> GetDynamic<TTable, TDynamicEntity>(Func<TTable, object> selector, 421 Func<object, TDynamicEntity> maker) where TTable : class 422 { 423 //todo 424 425 } 426 427 #endregion 428 429 #region Count 430 431 public virtual async Task<int> CountAsync() 432 { 433 //todo 434 } 435 436 public virtual async Task<int> CountByAsync(Expression<Func<T, bool>> where) 437 { 438 //todo 439 } 440 441 #endregion 442 443 #region Exists 444 445 public virtual bool Exists(string id) 446 { 447 throw new NotImplementedException(); 448 } 449 450 public virtual bool Exists(int id) 451 { 452 throw new NotImplementedException(); 453 } 454 455 public virtual async Task<bool> ExistsAsync(string id) 456 { 457 throw new NotImplementedException(); 458 } 459 460 public virtual async Task<bool> ExistsAsync(int id) 461 { 462 throw new NotImplementedException(); 463 } 464 465 public virtual bool Exists(Expression<Func<T, bool>> @where) 466 { 467 throw new NotImplementedException(); 468 } 469 470 public virtual async Task<bool> ExistsAsync(Expression<Func<T, bool>> @where) 471 { 472 throw new NotImplementedException(); 473 } 474 475 #endregion 476 477 478 #endregion 479 } |
http://blog.csdn.net/wodeai1235/article/details/54923072
View Details表示伪随机数生成器,这是一种能够产生满足某些随机性统计要求的数字序列的设备。 若要浏览此类型的.NET Framework 源代码,请参阅 Reference Source。 命名空间: System 程序集: mscorlib(位于 mscorlib.dll) 继承层次结构 System.Object System.Random 语法 C#
1 2 3 |
[SerializableAttribute] [ComVisibleAttribute(true)] public class Random |
构造函数 名称 说明 Random() 新实例初始化 Random 类,使用依赖于时间的默认种子值。 Random(Int32) 新实例初始化 Random 类,使用指定的种子值。 方法 名称 说明 Equals(Object) 确定指定的对象是否等于当前对象。(继承自 Object。) Finalize() 在垃圾回收将某一对象回收前允许该对象尝试释放资源并执行其他清理操作。(继承自 Object。) GetHashCode() 作为默认哈希函数。(继承自 Object。) GetType() 获取当前实例的 Type。(继承自 Object。) MemberwiseClone() 创建当前 Object 的浅表副本。(继承自 Object。) Next() 返回一个非负随机整数。 Next(Int32) 返回一个小于所指定最大值的非负随机整数。 Next(Int32, Int32) 返回在指定范围内的任意整数。 NextBytes(Byte[]) 用随机数填充指定字节数组的元素。 NextDouble() 返回一个大于或等于 0.0 且小于 1.0 的随机浮点数。 Sample() 返回一个介于 0.0 和 1.0 之间的随机浮点数。 ToString() 返回表示当前对象的字符串。(继承自 Object。) 说明 若要查看此类型的.NET Framework 源代码,请参阅 Reference Source。 您可以浏览源代码、 下载脱机查看参考资料和调试; 在逐句通过源 (包括修补程序和更新)see instructions. 伪随机数字从一组有限的数字选择以相同的概率。 因为数学算法可用于选择它们,但它们是充分随机实用的角度而言,所选的数字不完全随机的。 当前实现 Random 类根据 Donald E.Knuth 删减随机数生成器算法的修改版本。 有关详细信息,请参阅 D.e。 Knuth。 计算机编程,卷 2 的艺术︰ Seminumerical 算法。 Addison-wesley,Reading,MA,第三个版本,1997年。 若要生成加密性极安全的随机数字,如一个适合于创建随机密码,使用 RNGCryptoServiceProvider 类或从派生类 System.Security.Cryptography.RandomNumberGenerator。 在本主题中: 实例化的随机数字生成器 避免多个实例化 System.Random 类和线程安全 生成不同类型的随机数字 替换您自己的算法 如何使用到 System.Random… 检索相同的随机值序列 检索唯一的随机值序列 […]
View DetailsBigDecimal类 对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDecimal类,而且使用BigDecimal类也可以进行大数的操作。BigDecimal类的常用方法如表11-15所示。 表11-15 BigDecimal类的常用方法 序号 方 法 类型 描 述 1 public BigDecimal(double val) 构造 将double表示形式转换 为BigDecimal 2 public BigDecimal(int val) 构造 将int表示形式转换为 BigDecimal 3 public BigDecimal(String val) 构造 将字符串表示 形式转换为BigDecimal 4 public BigDecimal add(BigDecimal augend) 普通 加法 5 public BigDecimal subtract(BigDecimal subtrahend) 普通 减法 6 public BigDecimal multiply(BigDecimal multiplicand) 普通 乘法 7 public BigDecimal divide(BigDecimal divisor) 普通 除法 范例:进行四舍五入的四则运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
package org.lxh.demo11.numberdemo; import java.math.BigDecimal; class MyMath { public static double add(double d1, double d2) { // 进行加法运算 BigDecimal b1 = new BigDecimal(d1); BigDecimal b2 = new BigDecimal(d2); return b1.add(b2).doubleValue(); } public static double sub(double d1, double d2) { // 进行减法运算 BigDecimal b1 = new BigDecimal(d1); BigDecimal b2 = new BigDecimal(d2); return b1.subtract(b2).doubleValue(); } public static double mul(double d1, double d2) { // 进行乘法运算 BigDecimal b1 = new BigDecimal(d1); BigDecimal b2 = new BigDecimal(d2); return b1.multiply(b2).doubleValue(); } public static double div(double d1, double d2,int len) {// 进行除法运算 BigDecimal b1 = new BigDecimal(d1); BigDecimal b2 = new BigDecimal(d2); return b1.divide(b2,len,BigDecimal. ROUND_HALF_UP).doubleValue(); } public static double round(double d, int len) { // 进行四舍五入 操作 BigDecimal b1 = new BigDecimal(d); BigDecimal b2 = new BigDecimal(1); // 任何一个数字除以1都是原数字 // ROUND_HALF_UP是BigDecimal的一个常量, 表示进行四舍五入的操作 return b1.divide(b2, len,BigDecimal. ROUND_HALF_UP).doubleValue(); } } public class BigDecimalDemo01 { public static void main(String[] args) { System.out.println("加法运算:" + MyMath.round(MyMath.add(10.345, 3.333), 1)); System.out.println("乘法运算:" + MyMath.round(MyMath.mul(10.345, 3.333), 3)); System.out.println("除法运算:" + MyMath.div(10.345, 3.333, 3)); System.out.println("减法运算:" + MyMath.round(MyMath.sub(10.345, 3.333), 3)); } } |
BigDecimal是Java中用来表示任意精确浮点数运算的类,在BigDecimal中,使用unscaledValue × 10-scale来表示一个浮点数。其中,unscaledValue是一个BigInteger,scale是一个int。从这个表示方法来看,BigDecimal只能标识有限小数,不过可以表示的数据范围远远大于double,在实际应用中基本足够了。 下面提一下两个精度问题: 问题一:BigDecimal的精度问题(StackOverflow上有个家伙问了相关的问题)
1 2 3 4 5 |
System.out.println(new BigDecimal(0.1).toString()); // 0.1000000000000000055511151231257827021181583404541015625 System.out.println(new BigDecimal("0.1").toString()); // 0.1 System.out.println(new BigDecimal( Double.toString(0.1000000000000000055511151231257827021181583404541015625)).toString());// 0.1 System.out.println(new BigDecimal(Double.toString(0.1)).toString()); // 0.1 |
分析一下上面代码的问题(注释的内容表示此语句的输出) 第一行:事实上,由于二进制无法精确地表示十进制小数0.1,但是编译器读到字符串"0.1"之后,必须把它转成8个字节的double值,因此,编译器只能用一个最接近的值来代替0.1了,即0.1000000000000000055511151231257827021181583404541015625。因此,在运行时,传给BigDecimal构造函数的真正的数值是0.1000000000000000055511151231257827021181583404541015625。 第二行:BigDecimal能够正确地把字符串转化成真正精确的浮点数。 第三行:问题在于Double.toString会使用一定的精度来四舍五入double,然后再输出。会。Double.toString(0.1000000000000000055511151231257827021181583404541015625)输出的事实上是"0.1",因此生成的BigDecimal表示的数也是0.1。 第四行:基于前面的分析,事实上这一行代码等价于第三行 结论: 1.如果你希望BigDecimal能够精确地表示你希望的数值,那么一定要使用字符串来表示小数,并传递给BigDecimal的构造函数。 2.如果你使用Double.toString来把double转化字符串,然后调用BigDecimal(String),这个也是不靠谱的,它不一定按你的想法工作。 3.如果你不是很在乎是否完全精确地表示,并且使用了BigDecimal(double),那么要注意double本身的特例,double的规范本身定义了几个特殊的double值(Infinite,-Infinite,NaN),不要把这些值传给BigDecimal,否则会抛出异常。 问题二:把double强制转化成int,难道不是扔掉小数部分吗?
1 |
int x=(int)1023.99999999999999; // x=1024为什么? |
原因还是在于二进制无法精确地表示某些十进制小数,因此1023.99999999999999在编译之后的double值变成了1024。 所以,把double强制转化成int确实是扔掉小数部分,但是你写在代码中的值,并不一定是编译器生成的真正的double值。 验证代码:
1 2 3 4 5 |
double d = 1023.99999999999999; int x = (int) d; System.out.println(new BigDecimal(d).toString()); // 1024 System.out.println(Long.toHexString(Double.doubleToRawLongBits(d))); // 4090000000000000 System.out.println(x); // 1024 |
前面提过BigDecimal可以精确地把double表示出来还记得吧。 我们也可以直接打印出d的二进制形式,根据IEEE 754的规定,我们可以算出0x4090000000000000=(1024)。 […]
View Details[java] view plain copy print? public class HelloWorldwww{ public static void main(String args[]){ int num ; // 声明一个整型变量num num = 3 ; // 将整型变量赋值为3 // 输出字符串,这里用"+" 号连接变量 System.out.println("这是数字"+num); System.out.println("我有"+num+" 本书!"); } }
1 2 3 4 5 6 7 8 9 10 |
public class HelloWorldwww{ public static void main(String args[]){ int num ; // 声明一个整型变量num num = 3 ; // 将整型变量赋值为3 // 输出字符串,这里用"+" 号连接变量 System.out.println("这是数字"+num); System.out.println("我有"+num+" 本书!"); } } |
通过DOS编译 提示 错误:编码GBK的不可映射字符 检查: 1、 查本机区域语言设置中文没有问题 2、 此程序可以在eclipse上正常运行 右键properties-resource-text file encoding 查是UTF-8 解决方法: 1、运行是使用javac -encoding UTF-8HelloWorlewww.java 编译通过 2、记事本打开java源文件,另存为选择ANSI编码 编译通过 说明: ANSI:美国国家标准协会,系统预设的标准文字储存格式。简体中文编码GB2312,实际上它是ANSI的一个代码页936 UTF-8:通用字集转换格式,这是为传输而设计的编码,2进制,以8位为单元对Unicode进行编码,如果使用只能在同类位元组内支持8个位元的重要资料一类的旧式传输媒体,可选择UTF-8格式。 在UTF-8里,英文字符仍然跟ASCII编码一样,因此原先的函数库可以继续使用。而中文的编码范围是在0080-07FF之间,因此是2个字节表示(但这两个字节和GB编码的两个字节是不同的),用专门的Unicode处理类可以对UTF编码进行处理。 from:http://blog.csdn.net/l1028386804/article/details/46583279
View Details近日,需要满足测试需求,进行大数据并发测试时,报出【HTTP 错误 500.0 – Internal Server Error E:\PHP\php-cgi.exe – FastCGI 进程超过了配置的活动超时时限】 解决办法: IIS7->FastCGI设置->双击"php-cgi.exe"->"活动超时" 项默认是设置为70(秒),改为600(10分钟,此处根据需求设置可以略高~) 注意这个是全局那边设置的不是针对单个网站设置 打开IIS7.5, 点击 "FastCGI设置", 双击之前配置IIS支持PHP设置的php-cgi.exe, "活动超时" 项设置的长一些,默认是30,这里的单位是秒,可以设置为1200(即:20分钟) 针对iis 7.5 网站站点设置的方式: 在网站的高级设置里面,单击连接限制,默认为120秒,这里面更改的是每个站点的 from:http://www.jb51.net/article/39436.htm
View DetailsC# DateTime与时间戳的相互转换,包括JavaScript时间戳和Unix的时间戳。 1. 什么是时间戳 首先要清楚JavaScript与Unix的时间戳的区别: JavaScript时间戳:是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数。 Unix时间戳:是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。 可以看出JavaScript时间戳总毫秒数,Unix时间戳是总秒数。 比如同样是的 2016/11/03 12:30:00 ,转换为JavaScript时间戳为 1478147400000;转换为Unix时间戳为 1478147400。 2. JavaScript时间戳相互转换 2.1 C# DateTime转换为JavaScript时间戳 1 2 3 System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区 long timeStamp = (long)(DateTime.Now – startTime).TotalMilliseconds; // 相差毫秒数 System.Console.WriteLine(timeStamp); 2.2 JavaScript时间戳转换为C# DateTime 1 2 3 4 long jsTimeStamp = 1478169023479; System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区 DateTime dt = startTime.AddMilliseconds(jsTimeStamp); System.Console.WriteLine(dt.ToString("yyyy/MM/dd HH:mm:ss:ffff")); 3. Unix时间戳相互转换 3.1 C# DateTime转换为Unix时间戳 1 2 3 System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区 long timeStamp = (long)(DateTime.Now – startTime).TotalSeconds; // 相差秒数 System.Console.WriteLine(timeStamp); 3.2 Unix时间戳转换为C# DateTime 1 2 3 4 longunixTimeStamp = […]
View Detailswordpress Mail sitename字段处理不当导致多处远程代码执行漏洞修复方法,废话不多说,直接上截图 文件路径:wp-includes/class-phpmailer.php ,修复方法如上截图蓝色选中部分,代码如下: if (is_null($patternselect)) { $patternselect = self::$validator; } if (is_callable($patternselect)) { return call_user_func($patternselect, $address); } 把以上代码复制粘贴到对应的位置就可以了,可能因版本不同,粘贴的行数也不同,但应该都可以找到这个位置。 希望每一个关注王通seo的人看到这个都能够把这些漏洞修复方法转载到自己的空间去,让更多的人轻松修复自己的网站程序漏洞。 from:http://www.seo.net.cn/faq/2552.html
View Details编者按 / 英子 (题图中的照片摄于十年前,来自Flickr)不夸张地说,Kathy Sierra 算是 IT 界传奇人士,她是那种极为罕见的可以在开发、产品、设计之间做到无缝衔接的人。你可能没听说过她,然而她身兼数职,每一个职位都够份量—— 知名IT出版商 O’Reilly 超级畅销技术书 Head First 系列策划人 第一本 Head First 系列图书 Head First Java 作者 大型 Java 开发者社区 JavaRanch.com 创办人 几款游戏主创 加州大学洛杉矶分校新媒体与交互设计课程创办人 …… 另外一个让人比较震惊和遗憾的信息是,Kathy Sierra 是网络暴力受害者。作为知名的创作者、技术人士,2007年之前,她在传播编程技术方面非常活跃。2007年3月,在参加 O’Reilly ETech 会议演讲之前,她的博客和邮件收到了匿名者的死亡威胁,之后她停止了所有公开活动,至今也极少公开露面。目前网上关于她个人的信息大都是2007年之前的,前几年她开了Twitter,但又关了… 距离 Kathy Sierra 淡出公众视线已是十年之久,IT领域可谓日新月异。我们无法猜想,如果十年来她一直活跃在技术一线如今是怎样的光景?目前,她仍然写书,热衷养马…..只是,我们觉得跟 Kathy 的距离很远…… 感谢 Badass: Making Users Awesome 中文版《用户思维+:好产品让用户为自己尖叫》一书即将出版上架,因为这个契机,我们得以跟 Kathy 直接对话 ;感谢图灵访谈负责人六米费劲周折联系到 Kathy ,这篇访谈弥足珍贵。 结尾为大家送出10本《用户思维+:好产品让用户为自己尖叫》。 Kathy Sierra O’Reilly出版社 Head First 系列图书策划人之一,大型Java开发者社区 JavaRanch.com 创办人,多款教育类和娱乐类游戏主要开发人员。加州大学洛杉矶分校新媒体与交互设计课程创始人。她深谙产品交互之道和认知科学理论,多年来,一直帮助大公司、创业公司、非营利组织和教育者重新思考打造用户体验的方法,培养持续忠诚的用户。 O’Reilly Head First 系列图书策划人 Head First 是 O’Reilly Media 推出的一套入门指导型图书系列,由 Kathy Sierra 和 Bert Bates 策划创办。最初,该系列只涵盖编程和软件工程。由于该系列图书的成功,目前已经扩展至其他的主题,像科学、数学和商业等领域。Head First 系列强调图书的“非正统性”,强化读者的视觉感受和读者的参与度。图书增添了很多互动性强的谜题、笑话,摒弃“标准”的设计和布局,推崇会话式的写作风格,让读者可以参与到给定的话题当中。 目前,图灵翻译出版了《嗨翻C语言》《Head First JavaScript 程序设计》。 优秀的技术图书作者 最为知名的作品包括: Head First Java,Head First 系列第一本图书,2005年出版第1版,迄今仍是Java入门书的翘楚。 Badass: Making Users […]
View Details1.Math.Round:四舍六入五取偶
1 2 3 4 5 6 7 8 9 10 |
Math.Round(0.0) //0 Math.Round(0.1) //0 Math.Round(0.2) //0 Math.Round(0.3) //0 Math.Round(0.4) //0 Math.Round(0.5) //0 Math.Round(0.6) //1 Math.Round(0.7) //1 Math.Round(0.8) //1 Math.Round(0.9) //1 |
说明:对于1.5,因要返回偶数,所以结果为2。 2.Math.Ceiling:只要有小数都加1
1 2 3 4 5 6 7 8 9 10 |
Math.Ceiling(0.0) //0 Math.Ceiling(0.1) //1 Math.Ceiling(0.2) //1 Math.Ceiling(0.3) //1 Math.Ceiling(0.4) //1 Math.Ceiling(0.5) //1 Math.Ceiling(0.6) //1 Math.Ceiling(0.7) //1 Math.Ceiling(0.8) //1 Math.Ceiling(0.9) //1 |
说明:例如在分页算法中计算分页数很有用。 3.Math.Floor:总是舍去小数
1 2 3 4 5 6 7 8 9 10 |
Math.Floor(0.0) //0 Math.Floor(0.1) //0 Math.Floor(0.2) //0 Math.Floor(0.3) //0 Math.Floor(0.4) //0 Math.Floor(0.5) //0 Math.Floor(0.6) //0 Math.Floor(0.7) //0 Math.Floor(0.8) //0 Math.Floor(0.9) //0 |
from:https://www.cnblogs.com/rwh871212/p/6962099.html
View Detailspublic enum StringComparison { CurrentCulture, CurrentCultureIgnoreCase, InvariantCulture, InvariantCultureIgnoreCase, Ordinal, OrdinalIgnoreCase } CurrentCulture 使用区域敏感排序规则和当前区域比较字符串。 CurrentCultureIgnoreCase 使用区域敏感排序规则、当前区域来比较字符串,同时忽略被比较字符串的大小写。 InvariantCulture 使用区域敏感排序规则和固定区域比较字符串。 InvariantCultureIgnoreCase 使用区域敏感排序规则、固定区域来比较字符串,同时忽略被比较字符串的大小写。 Ordinal 使用序号排序规则比较字符串。 OrdinalIgnoreCase 使用序号排序规则并忽略被比较字符串的大小写,对字符串进行比较。 1.首先是StringComparison.Ordinal 在进行调用String.Compare(string1,string2,StringComparison.Ordinal)的时候是进行非语言(non-linguistic)上的比较,API运行时将会对两个字符串进行byte级别的比较,因此这种比较是比较严格和准确的,并且在性能上也很好,一般通过StringComparison.Ordinal来进行比较比使用String.Compare(string1,string2)来比较要快10倍左右.(可以写一个简单的小程序验证,这个挺让我惊讶,因为平时使用String.Compare从来就没想过那么多).StringComparison.OrdinalIgnoreCase就是忽略大小写的比较,同样是byte级别的比较.性能稍弱于StringComparison.Ordinal. 2.StringComparison.CurrentCulture 是在当前的区域信息下进行比较,这是String.Compare在没有指定StringComparison的时候默认的比较方式.例子如下: Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); //当前的区域信息是美国 string s1 = "visualstudio"; string s2 = "windows"; Console.WriteLine(String.Compare(s1, s2,StringComparison.CurrentCulture)); //输出"-1" Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-SE"); //当前的区域信息是瑞典 Console.WriteLine(String.Compare(s1, s2,StringComparison.CurrentCulture)); //输出"1" StringComarison.CurrentCultureIgnoreCase指在当前区域信息下忽略大小写的比较. 3.StringComarison.InvariantCulture 使用StringComarison.InvariantCulture来进行字符串比较,在任何系统中(不同的culture)比较都将得到相同的结果,他是使用CultureInfo.InvariantCulture的静态成员CompareInfo来进行比较操作的.例子如下: Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); //当前的区域信息是美国 string s1 = "visualstudio"; string s2 = "windows"; Console.WriteLine(String.Compare(s1, s2,StringComparison.InvariantCulture)); //输出"-1" Thread.CurrentThread.CurrentCulture = new CultureInfo("sv-SE"); //当前的区域信息是瑞典 Console.WriteLine(String.Compare(s1, s2,StringComparison.InvariantCulture)); //输出"-1" 参考文章:http://msdn.microsoft.com/netframework/default.aspx?pull=/library/en-us/dndotnet/html/StringsinNET20.asp from:http://www.cnblogs.com/zhw511006/archive/2010/07/09/1774591.html
View Details