Net面向对象程序设计-14-使用垃圾回收和资源管理.ppt

上传人:大米 文档编号:572731127 上传时间:2024-08-13 格式:PPT 页数:30 大小:277.50KB
返回 下载 相关 举报
Net面向对象程序设计-14-使用垃圾回收和资源管理.ppt_第1页
第1页 / 共30页
Net面向对象程序设计-14-使用垃圾回收和资源管理.ppt_第2页
第2页 / 共30页
Net面向对象程序设计-14-使用垃圾回收和资源管理.ppt_第3页
第3页 / 共30页
Net面向对象程序设计-14-使用垃圾回收和资源管理.ppt_第4页
第4页 / 共30页
Net面向对象程序设计-14-使用垃圾回收和资源管理.ppt_第5页
第5页 / 共30页
点击查看更多>>
资源描述

《Net面向对象程序设计-14-使用垃圾回收和资源管理.ppt》由会员分享,可在线阅读,更多相关《Net面向对象程序设计-14-使用垃圾回收和资源管理.ppt(30页珍藏版)》请在金锄头文库上搜索。

1、.NET.NET面向对象程序设计面向对象程序设计第第1414章章使用垃圾回收和资源管理使用垃圾回收和资源管理本章简介本章简介使用使用GC编写写代代码,用用析析构构器器终结一一个个对象象时运运行行这些些代代码编写写try/finally语句句编写写using语句句14.1 对象的生存期对象的生存期对象的象的创建示例:建示例:uSquare mySquare=new Square();从开从开发人人员的角度看,的角度看,new是一个原子是一个原子级的操作的操作在最底在最底层,对象的象的创建建实际分两步走:分两步走:u首首先先,new操操作作必必须须从从heap中中分分配配一一些些原原始始内内存存,

2、在在创建对象阶段,你无法进行任何干涉创建对象阶段,你无法进行任何干涉u然然后后,new操操作作必必须须将将那那些些原原始始内内存存转转换换成成一一个个对对象象,它它必必须须初初始始化化对对象象,在在构构造造器器的的帮帮助助下下,可可以以对对这这一一阶段进行控制阶段进行控制创建建对象后,可以使用象后,可以使用.操作符操作符访问它的成它的成员可以可以让其他引用其他引用变量引用同一个量引用同一个对象象销毁对象也分两步走象也分两步走u首首先先,runtime必必须须执执行行一一些些清清理理工工作作,在在一一个个析析构构器器destructor的帮助下,你可以对这一阶段进行控制的帮助下,你可以对这一阶段

3、进行控制u然然后后,runtime必必须须将将之之前前被被对对象象占占有有的的内内存存归归还还给给堆堆,对对象象的的内内存存必必须须回回收收,同同样样,你你对对这这一一阶阶段段仍仍然然没没有有任何控制权任何控制权销毁一一个个对象象,并并将将内内存存归还给堆堆的的过程程称称为垃垃圾回收(圾回收(garbage collection)5示例:示例:01: using System;02:03: class Account04: 05:06: 07:08: class Bank09: 10: private Account bankAccount;11:12: public void SetAcco

4、unt (Account newAccount)13: 14: bankAccount = newAccount;15: 16: 17:18: class Tester19: 20: public static void Main()21: 22: Bank bank1;24: Account account1;25: Account account2;27: account1 = new Account();29: account1 = null;31: account1 = new Account();32: account2 = new Account();34: account1 =

5、account2;36: bank1 = new Bank();37: bank1.SetAccount(new Account();39: bank1 = null;41: DoingAccountStuff();42: 44: public static void DoingAccountStuff()45: 46: Account localAccount;47: localAccount = new Account();48: 49: 61、将将null引引用用赋赋值值给给对对象象的的所有引用所有引用72、将将一一个个表表示示对对对对象象A的的唯唯一一引引用用的的应应用用变变量量赋赋值

6、值给给另另一一个个不不同同的的引引用用对对象象时,对象时,对象A被废弃被废弃83、当当对对象象A包包含含对对象象B的的唯唯一一引引用用时时,若若废废弃弃对对象象A时时,对对象象A和对象和对象B都被废弃都被废弃4、当当一一个个包包含含对对某某对对象象的的唯唯一一引引用用的的本本地地变变量量越越过过作作用用域域时时,此对象就会被废除此对象就会被废除14.1.1 编写析构器编写析构器使使用用析析构构器器,可可以以执行行对象象被被垃垃圾圾回回收收时需需要要执行行的的任任何何清理工作清理工作析析构构器器也也是是一一个个特特殊殊的的方方法法,只只是是runtime会会在在一一个个对象象的最后一个引用消失后

7、的最后一个引用消失后调用它用它 public static int InstanceCount() return this.instanceCount; . private static int instanceCount = 0; class Tally public Tally() this.instanceCount+; Tally() this.instanceCount-; C# 无需太多的内存管理。这是因为 .NETFramework垃圾回收器会隐式地管理对象的内存分配和释放。但是,当应用程序封装窗口、文件和网络连接这类非托管资源时,应当使用析构函数释放这些资源。当对象符合析构时,

8、垃圾回收器将运行对象的Finalize方法。 析构器存在一些非常重要的限制析构器存在一些非常重要的限制析构器只适用于引用析构器只适用于引用类型,不能在型,不能在值类型中声明析构器型中声明析构器struct Tally Tally() . / compile-time error 不不能能为析析构构器器指指定定一一个个访问修修饰符符,因因为你你永永远不不在在自自己己的代的代码中中调用析构器用析构器-总是由垃圾回收器来帮你是由垃圾回收器来帮你调用用public Tally() . / compile-time error析析构构器器不不能能获取取任任何何参参数数,同同样的的,这是是由由于于你你永永

9、远不不由由你自己你自己调用析构器用析构器Tally(int parameter) . / compile-time error内内部部,编译器器自自动将将一一个个析析构构器器转换成成对Object.Finalize方法的一个重写版本方法的一个重写版本编译器将以下析构器器将以下析构器uclass Tally u u Tally() / your code goes here u转换成以下形式成以下形式uclass Tally u u protected override void Finalize() u u try / your code goes here u finally base.Fi

10、nalize(); u u14.1.2 为什么要使用垃圾回收器为什么要使用垃圾回收器在在C#中中,程程序序员永永远不不能能亲自自销毁一一个个对象象,没没有任何有任何语法支持法支持这个操作个操作假如由程序假如由程序员承担承担销毁对象的象的责任,可能任,可能导致:致:u忘记销毁一个对象忘记销毁一个对象u试试图图销销毁毁一一个个活活动动对对象象,对对象象是是通通过过引引用用来来访访问问的的,假假如如一一个个类类容容纳纳了了一一个个已已销销毁毁的的对对象象的的引引用用,该该引引用用会成为虚悬引用,可能带来风险会成为虚悬引用,可能带来风险u试图多次销毁同一个对象试图多次销毁同一个对象垃圾回收器保垃圾回收

11、器保证:u每个对象都会被销毁,它的析构器会运行每个对象都会被销毁,它的析构器会运行u每个对象都只销毁一次每个对象都只销毁一次u每每个个对对象象都都只只在在它它不不可可抵抵达达时时,即即不不再再存存在在对对该该对对象象的引用时才会销毁的引用时才会销毁垃圾回收的垃圾回收的时机:机:u垃圾回收不一定在对象不再需要之后立即进行垃圾回收不一定在对象不再需要之后立即进行u程序员不知道对象的销毁顺序程序员不知道对象的销毁顺序u只有当对象进行垃圾回收的时候,才会运行析构器只有当对象进行垃圾回收的时候,才会运行析构器1.可可以以调调用用静静态态方方法法System.GC.Collect,从从而在一个程序中调用垃

12、圾回收器而在一个程序中调用垃圾回收器2.然而,除非在极少情况下,不建议这样做然而,除非在极少情况下,不建议这样做3.该该方方法法将将启启动动垃垃圾圾回回收收器器,但但具具体体的的回回收收过过程程是是异异步步进进行行的的,当当程程序序结结束束时时,程程序序员员仍仍然不知道对象是否已经销毁然不知道对象是否已经销毁4.所以让所以让runtime决定垃圾回收的最佳时机决定垃圾回收的最佳时机14.1.3垃圾回收器的工作机理垃圾回收器的工作机理垃垃圾圾回回收收器器在在它它自自己己的的线程程中中运运行行,而而且且只只有有在在特特定定的的时候才会候才会执行行它它运运行行时,应用用程程序序中中的的其其他他线程程

13、将将暂停停,这是是由由于于垃垃圾圾回回收收器器可可能能需需要要移移动对象象并并更更新新对象象引引用用,假假如如对象象仍仍在在使用,就不能使用,就不能进行行这些操作些操作垃圾回收器采取的步垃圾回收器采取的步骤u构造包含所有可能抵达对象的一个构造包含所有可能抵达对象的一个mapu检检查查是是否否有有任任何何不不可可达达的的对对象象含含有有一一个个需需要要运运行行的的析析构构器器,需需要要终结的任何不可达的对象都会放到一个特殊的队列中终结的任何不可达的对象都会放到一个特殊的队列中u回回收收剩剩余余的的不不可可达达的的对对象象,为为此此,它它会会在在堆堆中中向向下下移移动动可可抵抵达达的的对象,从而对

14、对象,从而对heap进行碎片整理,并释放位于进行碎片整理,并释放位于heap顶部的内存顶部的内存u然后,它允许其他线程恢复执行然后,它允许其他线程恢复执行u它在一个单独线程中,对需要终结的不可达对象执行它在一个单独线程中,对需要终结的不可达对象执行finalize操作操作14.1.4 慎用析构器慎用析构器写写一一个个含含有有析析构构器器的的类,会会使使代代码和和垃垃圾圾回回收收过程程变得更复得更复杂,而且,而且还会影响程序的运行速度会影响程序的运行速度14.2 资源管理资源管理有有的的资源源可可能能过于于宝宝贵,用用完完应该马上上释放放,所所以不适合在析构器中以不适合在析构器中释放放解决方法:

15、解决方法:专门创建一个建一个disposal方法方法disposal方方法法:就就是是对资源源进行行处置置的的一一个个方方法法,假假如如一一个个类有有disposal方方法法,就就可可以以显式式的的调用用它,从而控制何它,从而控制何时释放放资源源disposal方方法法强调的的是是方方法法的的用用途途而而不不是是名名称称,一个一个disposal方法可以使用任何有效地方法可以使用任何有效地C#方法名方法名14.2.1 disposal方法方法示示例例:System.IO命命名名空空间的的TextReader类,该类含含有有一一个个名名为Close的的virtual方方法法,它它负责关关闭流流u

16、TextReader reader = new StreamReader(filename);ustring line;uwhile (line = reader.ReadLine() != null)ulConsole.WriteLine(line);uureader.Close();问题:问题:如如果果对对ReaLine的的调调用用抛抛出出一一个个异异常常,对对close的的调调用用就就不不会会发发生生如如果果经经常常发发生生这这种种情情况况,最最终终会耗尽内存会耗尽内存14.2.2 异常安全的异常安全的disposal方法方法为了了确确保保disposal方方法法(Close()总是是得

17、得到到调用用,一一个解决的个解决的办法是在法是在finally块中中调用用disposal方法方法例如:例如:TextReader reader = new StreamReader(filename);try string line; while (line = reader.ReadLine() != null) Console.WriteLine(line); finally reader.Close();缺点:缺点:如如果果必必须须摧摧毁毁多多个个资资源源,局局面面很很快快会会变变得难以控制得难以控制在某些情况下,可能必须修改代码在某些情况下,可能必须修改代码它不能创建解决方案的一个抽

18、象它不能创建解决方案的一个抽象对对资资源源的的引引用用保保留留在在finally块块之之后后的的作作用用域域中中,导导致致不不小小心心试试图图使使用用一一个个已已经经释放的资源释放的资源14.2.3 using 语句语句using语句句提提供供了了一一个个脉脉络清清晰晰的的机机制制来来控控制制资源源的生存期的生存期可可以以创建建一一个个对象象,这个个对象象会会在在using语句句块结束束时销毁语法如下:法如下:uusing ( type variable = initialization )ulStatementBlocku下下面面是是确确保保代代码码总总是是为为一一个个TextReader调

19、调用用Close的的最最佳佳方法方法using (TextReader reader = new StreamReader(filename) string line; while (line = reader.ReadLine() != null) Console.WriteLine(line); 等价于:等价于:TextReader reader = new StreamReader(filename);try string line; while (line = reader.ReadLine() != null) Console.WriteLine(line); finally if

20、(reader != null) (IDisposable)reader).Dispose(); 在在 using语 句句 中中 声声 明明 的的 变 量量 必必 须 是是 实 现 了了Idisposable接口的一个接口的一个类型型Idisposable接接口口在在System命命名名空空间中中,只只包包含含一个名一个名为Disposable的方法的方法namespace SysteminterfaceIDisposablevoidDispose();StreamReader类恰恰好好实现了了Idisposal接接口口,它它的的Dispose方法会方法会调用用Close来关来关闭流流我我们可

21、可以以将将using语句句作作为一一种种清清晰晰的的、异异常常安安全全的以及可靠的方式来保的以及可靠的方式来保证一个一个资源源总是被是被释放放特点:特点:u需要需要disposal多个资源时,具有良好的可扩展性多个资源时,具有良好的可扩展性u不影响程序代码的逻辑不影响程序代码的逻辑u对问题进行良好的抽象,避免重复性编码对问题进行良好的抽象,避免重复性编码u非非常常健健壮壮,using语语句句结结束束后后,就就不不能能使使用用using语语句句中声明的变量中声明的变量14.2.4 从析构器中调用从析构器中调用Disposal方法方法对析析构构器器的的调用用肯肯定定会会发生生,只只是是不不知知道道

22、具具体体在在什么什么时候候另另一一方方面面,能能够确确切切地地知知道道什什么么时候候发生生对Dispose方方法法的的调用用,只只是是无无法法保保证它它会会实际的的发生,因生,因为它要求程序它要求程序员记住写一个住写一个using语句句通通过从从析析构构器器中中调用用Dispose方方法法,就就能能保保证它它总是得到运行是得到运行这样就就提提供供了了一一个个有有效效的的保保障障:也也许忘忘记了了调用用Dispose方法,但至少能保方法,但至少能保证它得到它得到调用用class Example : IDisposableprivate Resource scarce; private bool

23、disposed = false;Example() Dispose();public virtual void Dispose() if (!this.disposed) t ry / release scarce resource here finally this.disposed = true; GC.SuppressFinalize(this); public void SomeBehavior() checkIfDisposed(); .private void checkIfDisposed() if (this.disposed) throw new ObjectDispose

24、dException(“示例示例: object has been disposed of); 课本本260页练习2701: using System; 03: class Bacterium 04: 05: private static int bacteriaCreated; 06: private static int tempBacteriaDestructed; 07: private static int totalBacteriaDestructed; 08: private static bool showBacteriaDestructed; 09: private stat

25、ic bool hasGCJustRun; 11: private int number; 12: private string name; 13: private string shape; 14: private string growthMethod; 15: private string group; 16: 17: public Bacterium () 18: 19: if (hasGCJustRun) 20: 21: Console.WriteLine(Bacterium objects destructed during GC Run: 0, 22: tempBacteriaD

26、estructed); 23: Console.WriteLine(Difference between bacteria created + 24: and bacteria destructed 0, 25: (bacteriaCreated - totalBacteriaDestructed); 26: Console.WriteLine(Resuming creating bacteria from number: 0n, 27: bacteriaCreated); 28: hasGCJustRun = false; 29: 2831: bacteriaCreated+; 32: nu

27、mber = bacteriaCreated; 33: name = Streptococcus; 34: shape = round; 35: growthMethod = chains; 36: group = alpha; 37: 39: static Bacterium () 40: 41: bacteriaCreated = 0; 42: tempBacteriaDestructed = 0; 43: totalBacteriaDestructed = 0; 44: showBacteriaDestructed = false; 45: hasGCJustRun = false; 4

28、6: 48: Bacterium() 49: 50: if(!hasGCJustRun) 51: 52: Console.WriteLine(Creation temporarily stopped + 53: at bacteria number: 0 to perform destruction, bacteriaCreated); 54: hasGCJustRun = true; 55: tempBacteriaDestructed = 0; 56: 57: if (showBacteriaDestructed) 58: 59: Console.WriteLine(Bacteria: 0

29、 destructed, number); 60: 61: tempBacteriaDestructed+; 62: totalBacteriaDestructed+; 63: 2965: public static void SetShowBacteriaDestructed (bool showIt) 66: 67: showBacteriaDestructed = showIt; 68: 69: 70: public static int GetTotalBacteriaDestructed () 71: 72: return totalBacteriaDestructed; 73: 7

30、4: 75: public static int GetTotalBacteriaCreated () 76: 77: return bacteriaCreated; 78: 79: 80: 81: class Body 82: 83: public static void Main() 84: 85: int bacteriaCreatedBeforeCollect; 86: int maxBacteria; 87: Bacterium newBacterium; 88: 3089: Console.Write(How many bacteria do you want to create?

31、 ); 90: maxBacteria = Convert.ToInt32(Console.ReadLine(); 91: Console.Write(Enter amount of bacteria to create + 92: before asking GC to run: ); 93: bacteriaCreatedBeforeCollect = Convert.ToInt32(Console.ReadLine(); 94: Console.Write(Do you want to see each + 95: bacterium number when destructed? Y)

32、es N)o ); 96: if (Console.ReadLine().ToUpper() = Y) 97: Bacterium.SetShowBacteriaDestructed (true); 98: else 99: Bacterium.SetShowBacteriaDestructed (false);100: Console.WriteLine( nCreation commencing n);102: for (int i = 0; i maxBacteria; i+)103: 104: newBacterium = new Bacterium();105: if (i = (b

33、acteriaCreatedBeforeCollect - 1)106: 107: Console.WriteLine(Initiating GC to run +108: after bacteria number: 0 has been created, (i + 1);109: GC.Collect();110: 111: 113: Console.WriteLine( nCreation stopped at bacterium number: 0 ,114: Bacterium.GetTotalBacteriaCreated();115: Console.WriteLine(Total Bacteria objects destructed +116: during execution of program: 0 ,117: Bacterium.GetTotalBacteriaDestructed();118: 119:

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号