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调用

           

            }

        }

  • 相关阅读:
    【Codeforces 349B】Color the Fence
    【Codeforces 459D】Pashmak and Parmida's problem
    【Codeforces 467C】George and Job
    【Codeforces 161D】Distance in Tree
    【Codeforces 522A】Reposts
    【Codeforces 225C】Barcode
    【Codeforces 446A】DZY Loves Sequences
    【Codeforces 429B】Working out
    【Codeforces 478C】Table Decorations
    【Codeforces 478C】Table Decorations
  • 原文地址:https://www.cnblogs.com/bingbinggui/p/4461056.html
Copyright © 2011-2022 走看看