好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

延迟初始化

延迟初始化

概念:一个对象的延迟初始化(也称延迟实例化)意味着该对象的创建将会延迟至第一次使用该对象时。   延迟初始化主要用于提高性能,避免浪费计算,并减少程序内存要求。

以下是最常见的方案:

有一个对象的创建开销很大时,应用程序可能不会使用它。   例如,假定您在内存中有一个  Customer   对象,该对象的  Orders   属性返回一个  Orders  对象。   初始化  Orders  对象可能需要创建  Orders  对象的一个大数组( Orders[] ),并可能需要数据库连接。   如果用户从不访问  Orders  属性,则没有理由使用系统内存或计算周期来创建  Orders  对象。   通过使用  Lazy<Orders>  将  Orders  对象声明为延迟初始化,可以避免在不使用该对象的情况下浪费系统资源。

有一个对象的创建开销很大,您想要将创建它的时间延迟到完成其他开销大的操作之后。   例如,假定您的应用程序在启动时加载若干个对象实例,但只有一些对象实例需要立即执行。   通过将不必要的对象的初始化延迟到已创建必要的对象之后,可以提高应用程序的启动性能。

尽管您可以编写自己的代码来执行迟缓初始化,但我们建议改用  System . . :: . Lazy < (Of  < ( T > ) > )  类。   Lazy < (Of  < ( T > ) > )  支持线程安全( 在一个线程中创建实例后,对其它线也是共享的 ),并提供一致的异常传播策略。

基本语法:

 1  Lazy<Orders> Orders= new  Lazy<Orders>();

另外,还可以在  Lazy < (Of  < ( T > ) > )  构造函数中传递一个委托,用于在创建时调用包装类的特定构造函数重载,并执行所需的任何其他初始化步骤,如以下示例中所示。

 1  Lazy<Orders> _orders =  new  Lazy<Orders>(() =>  new  Orders(OrderSorted.CreateDate));  //  可以重载指定的构造函数,如用来实现一种排序规则 

在创建  Lazy  对象之后,在第一次访问  Lazy < (Of  < ( T > ) > )  实例的  Value  属性之前,将不会创建  Orders  的实例。   在第一次访问包装类型时,将会创建并返回该包装类型,并将其存储起来以备任何将来的访问。

 1   //   当满足一种条件时,再去创建orders对象 
 2   if  (displayOrders ==  true  )
  3   {
  4       DisplayOrders(_orders.Value.OrderData);
  5   }
  6   else 
 7   {
  8       //   Don't waste resources getting order data. 
 9  }

线程安全初始化

默认情况下, Lazy < (Of  < ( T > ) > )  对象是线程安全的。   这意味着如果构造函数未指定线程安全性的类型,它创建的  Lazy < (Of  < ( T > ) > )  对象都是线程安全的。   在多线程方案中,要访问线程安全的  Lazy < (Of  < ( T > ) > )  对象的  Value  属性的第一个线程将为所有线程上的所有后续访问初始化该对象,并且所有线程都共享相同数据。   因此,由哪个线程初始化对象并不重要,争用条件将是良性的。

  1   //   Initialize the integer to the managed thread id of the 
   2   //   first thread that accesses the Value property. 
  3  Lazy< int > number =  new  Lazy< int >(() => 
  4        Thread.CurrentThread.ManagedThreadId);
   5  
  6  Thread t1 =  new  Thread(() => 
  7      Console.WriteLine( "  number on t1 = {0} ThreadID = {1}  "  ,
   8                         number.Value, Thread.CurrentThread.ManagedThreadId));
   9   t1.Start();
  10  
 11  Thread t2 =  new  Thread(() => 
 12      Console.WriteLine( "  number on t2 = {0} ThreadID = {1}  "  ,
  13                         number.Value, Thread.CurrentThread.ManagedThreadId));
  14   t2.Start();
  15  
 16  Thread t3 =  new  Thread(() => 
 17      Console.WriteLine( "  number on t3 = {0} ThreadID = {1}  "  , number.Value,
  18                         Thread.CurrentThread.ManagedThreadId));
  19   t3.Start();
  20  
 21   //   Ensure that thread IDs are not recycled if the 
  22   //   first thread completes before the last one starts. 
 23   t1.Join();
  24   t2.Join();
  25   t3.Join();
  26  
 27   /*   Sample Output:
  28       number on t1 = 11 ThreadID = 11
  29       number on t3 = 11 ThreadID = 13
  30       number on t2 = 11 ThreadID = 12
  31       Press any key to exit.
  32   */ 

若要通过使用延迟初始化来实现一个公共属性,请将该属性的支持字段定义为  Lazy < (Of  < ( T > ) > )  对象,并从该属性的  get  访问器返回  Value  属性。

  1   class   Customer
   2   {
   3       private  Lazy<Orders>  _orders;
   4       public   string  CustomerID { get ;  private   set  ;}
   5       public  Customer( string   id)
   6       {
   7          CustomerID =  id;
   8          _orders =  new  Lazy<Orders>(() =>
  9           {
  10               //   You can specify any additonal 
  11               //   initialization steps here(这个Orders不会应该Customer的实例化,而被实例化,它只会在使时,才会被实例化) 
 12               return   new  Orders( this  .CustomerID);
  13           });
  14       }
  15  
 16       public   Orders MyOrders
  17       {
  18           get 
 19           {
  20               //   Orders is created on first access here. 
 21               return   _orders.Value;
  22           }
  23       }
  24  }

延时实例化,在大对象时使用比较多,使用 Lazy < (Of  < ( T > ) > ) 我们还可以实现一种泛型的单例基类,看代码:

  1    ///   <summary> 
  2       ///   泛型单例基类
   3       ///   </summary> 
  4       public   abstract   class  Singleton<TEntity>  where  TEntity :  class 
  5       {
   6           private   static   readonly  Lazy<TEntity>  _instance
   7            =  new  Lazy<TEntity>(() =>
  8             {
   9                 var  ctors =  typeof  (TEntity).GetConstructors(
  10                     BindingFlags.Instance
  11                    |  BindingFlags.NonPublic
  12                    |  BindingFlags.Public);
  13                 if  (ctors.Count() !=  1  )
  14                     throw   new  InvalidOperationException(String.Format( "  Type {0} must have exactly one constructor.  " ,  typeof  (TEntity)));
  15                 var  ctor = ctors.SingleOrDefault(c => c.GetParameters().Count() ==  0  &&  c.IsPrivate);
  16                 if  (ctor ==  null  )
  17                     throw   new  InvalidOperationException(String.Format( "  The constructor for {0} must be private and take no parameters.  " ,  typeof  (TEntity)));
  18                 return  (TEntity)ctor.Invoke( null  );
  19             });
  20  
 21           public   static   TEntity Instance
  22           {
  23               get  {  return   _instance.Value; }
  24           }
  25      }

 

参考 文献:

http://technet.microsoft.com/zh-cn/magazine/dd997286%28VS.95%29.aspx

http://www.fascinatedwithsoftware.com/blog/post/2011/07/13/A-Generic-Singleton-Class.aspx

 

返回目录   基础才是重中之重系列~目录(永久更新中)

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于延迟初始化的详细内容...

  阅读:40次