zoukankan      html  css  js  c++  java
  • 第十三节:编程控制垃圾回收器

    System.GC类型允许应用程序在某种程度上直接控制垃圾回收。例如:可以读取GC.MaxGeneration属性来查询托管堆支持的最大代数;该属性总是返回2。

    还可以调用以下静态方法来强迫执行一次垃圾回收:

          public static void Collect();

          public static void Collect(int generation);

          public static void Collect(int generation, GCCollectionMode mode);

    第二个方法允许指定回收那一代吗,传递0导致第0代回收,传递1导致第1代和第0代回收,传递2导致第2代、第1代、第0代回收。无参的版本导致对所有代执行一次回收。

    第三个方法重载版本允许传递一个代和一个GCCollectionMode。下面总结各种GC回收模式符号。

    GCCollectionMode枚举定义的符号:

    Default :等同于不传递任何符号名称。目前还等同与传递Forced,但CLR未来的版本可能进行修改

    Forced:强迫回收指定的代(以及低于它的代)

    Optimized 只有在能够释放大量内存或者能减少大量碎片化的前提下,才执行回收。如果垃圾回收效果不佳,当前调用就没有任何效果。

    大多数情况下应避免调用任何Collect方法;最好是让垃圾回收器自行斟酌执行,并根据实际的应用程序的行为来调整各个代的预算。但是,如果你要写一个CUI(控制台用户界面)和GUI(图形用户界面)应用程序,应用程序代码将拥有进程和那个进程中的CLR.对于这种应用程序,你可能建议在特定时间发生一次垃圾回收;为此,请将GCCollectionMode设为Optimized并调用Collect。一般情况下,Default和Forced这两种模式是供调试和测试用的。

    例如,假设刚才发生了某个非重复性的事件,并导致大量旧对象死亡,就可考虑手动调用一次Collect方法。对于非重复性的事件,垃圾回收器基于历史而对未来的预测可能不会准确。所以在这种情况下调用Collect方法时合适的。

    例如:在应用程序初始化完成以后,或者在用户保存了一个数据文件后,应用程序就适合对所有代强制执行一次垃圾回收。一个Window窗体宿主在网页上时,每次页面卸载后,都要执行一次完全的垃圾回收,不要为了改善应用程序的响应时间而显示调用Collect方法;只应处于减少进程工作集的目的而调用它。

    GC类还提供了一个WaitForPendingFinalizers方法。该方法会挂起调用线程,直到处理freachable队列的线程清空该队列,完成对每个对象的Finalize方法的调用。在大多数应用程序中就没有必要调用该方法,但我见过下面这样的代码:

    GC.Collect();

    GC.WaitForPendingFinalizers();

    GC.Collect();

    以上代码强制开始一次垃圾回收。回收完毕后,不需要终结的对象的内存将被回收。但需要终结的对象的内存还不能回收。第一个Collect调用返回后,专门负责终结操作的那个线程以异步方式调用Finalize方法。对WaitForPendingFinalizers方法的调用使应用程序线程进入睡眠状态。直到所有Finalize方法调用完毕。WaitForPendingFinalizers方法返回后,所有被终结的对象都以成为垃圾。这时,第二个Collect调用强制开始另一次垃圾回收,从而回收那些垃圾。

    对于某些应用程序(尤其是喜欢在内存中容纳大量对象的服务器应用程序),如果对包含第2代在内的对象执行完全的垃圾回收,花费的时间可能过长。如果一次回收要花很长的时间才能完成,客户端请求可能会超时。为了适应这种应用程序的需求,GC类提供了一个RegisterForFullGCNotification方法。利用这个方法和一些额外的辅助方法(WaitForFullGCApproach、 WaitForFullGCComplete、 CancelFullGCNotification)应用程序会在垃圾回收器即将执行一次垃圾回收时收到通知。然后,应用程序可调用GC.Collect在一个更恰当的时间强制执行一次回收。应用程序也可与另一个服务器通信,对客户端的请求进行更好的负载平移。

    最后,GC类还提供了两个静态方法来辅助你判断对象当前在哪一代中:

    int GetGeneration(object obj);

    int GetGeneration(WeakReference wo);

    第一个版本是获取一个对象引用作为参数,第二版本是获取WeakReference引用作为参数。这两个方法返回的是0到GC.MaxGeneration的一个值。

    一下代码有助于理解代的工作原理:

    sealed class GenObj

        {

            ~GenObj()

            {

                Console.WriteLine("In Finalize method");

            }

        }

        class Program

        {

            static void Main(string[] args)

            {

                Console.WriteLine("Maximun generation:" + GC.MaxGeneration);

                Object o = new GenObj();

                Console.WriteLine("Gen" + GC.GetGeneration(o));//0

                //执行一次垃圾回收提升对象代

                GC.Collect();

                Console.WriteLine("Gen" + GC.GetGeneration(o));//1

                GC.Collect();

                Console.WriteLine("Gen" + GC.GetGeneration(o));//2

                GC.Collect();

                Console.WriteLine("Gen" + GC.GetGeneration(o));//2

                o = null;

                Console.WriteLine("Collecting Gen 0");

                GC.Collect(0);//回收第0代

                GC.WaitForPendingFinalizers();//Finalize未调用

                Console.WriteLine("Collection Gens 0, and 1");

                GC.Collect(1);//回收第0代和第1代

                GC.WaitForPendingFinalizers();//Finalize未调用

                Console.WriteLine("Collection Gens 0, 1 and 2");

                GC.Collect(2);

                GC.WaitForPendingFinalizers();//Finalize调用

           

            }

        }

  • 相关阅读:
    对数据劫持 OR 数据代理 的研究------------引用
    对React性能优化的研究-----------------引用
    对abel 转译 class 过程的研究----------------------引用
    对vue-router的研究--------------引用
    对JavaScript 引擎基础:原型优化的研究 -----------------------引用
    对vue源码之缓存的研究--------------引用
    对前端数据结构与算法的研究----------------引用
    正则表达式巩固_从别的资料上弄下来的
    十进制转换
    cmd 安装第三方库问题
  • 原文地址:https://www.cnblogs.com/bingbinggui/p/4461056.html
Copyright © 2011-2022 走看看