Java對象的生命周期分析
Java對象的生命周期大致包括三個(gè)階段:對象的創(chuàng)建,對象的使用,對象的清除。因此,對象的生命周期長度可用如下的表達(dá)式表示:T = T1 + T2 +T3。其中T1表示對象的創(chuàng)建時(shí)間,T2表示對象的使用時(shí)間,而T3則表示其清除時(shí)間。由此,我們可以看出,只有T2是真正有效的時(shí)間,而T1、T3則是對象本身的開銷。下面再看看T1、T3在對象的整個(gè)生命周期中所占的比例。
我們知道,Java對象是通過構(gòu)造函數(shù)來創(chuàng)建的,在這一過程中,該構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)也都會(huì)被自動(dòng)調(diào)用。另外,默認(rèn)情況下,調(diào)用類的構(gòu)造函數(shù)時(shí),Java會(huì)把變量初始化成確定的值:所有的對象被設(shè)置成null,整數(shù)變量(byte、short、int、long)設(shè)置成0,float和double變量設(shè)置成0.0,邏輯值設(shè)置成false。所以用new關(guān)鍵字來新建一個(gè)對象的時(shí)間開銷是很大的,如表1所示。
表1 一些操作所耗費(fèi)時(shí)間的對照表
從表1可以看出,新建一個(gè)對象需要980個(gè)單位的時(shí)間,是本地賦值時(shí)間的980倍,是方法調(diào)用時(shí)間的166倍,而若新建一個(gè)數(shù)組所花費(fèi)的時(shí)間就更多了。
再看清除對象的過程。我們知道,Java語言的一個(gè)優(yōu)勢,就是Java程序員勿需再像C/C++程序員那樣,顯式地釋放對象,而由稱為垃圾收集器(Garbage Collector)的自動(dòng)內(nèi)存管理系統(tǒng),定時(shí)或在內(nèi)存凸現(xiàn)出不足時(shí),自動(dòng)回收垃圾對象所占的內(nèi)存。凡事有利總也有弊,這雖然為Java程序設(shè)計(jì)者提供了極大的方便,但同時(shí)它也帶來了較大的性能開銷。這種開銷包括兩方面,首先是對象管理開銷,GC為了能夠正確釋放對象,它必須監(jiān)控每一個(gè)對象的運(yùn)行狀態(tài),包括對象的申請、引用、被引用、賦值等。其次,在GC開始回收“垃圾”對象時(shí),系統(tǒng)會(huì)暫停應(yīng)用程序的執(zhí)行,而獨(dú)自占用CPU。
因此,如果要改善應(yīng)用程序的性能,一方面應(yīng)盡量減少創(chuàng)建新對象的次數(shù);同時(shí),還應(yīng)盡量減少T1、T3的時(shí)間,而這些均可以通過對象池技術(shù)來實(shí)現(xiàn)。
對象池技術(shù)的基本原理
對象池技術(shù)基本原理的核心有兩點(diǎn):緩存和共享,即對于那些被頻繁使用的對象,在使用完后,不立即將它們釋放,而是將它們緩存起來,以供后續(xù)的應(yīng)用程序重復(fù)使用,從而減少創(chuàng)建對象和釋放對象的次數(shù),進(jìn)而改善應(yīng)用程序的性能。事實(shí)上,由于對象池技術(shù)將對象限制在一定的數(shù)量,也有效地減少了應(yīng)用程序內(nèi)存上的開銷。
實(shí)現(xiàn)一個(gè)對象池,一般會(huì)涉及到如下的類:
1)對象池工廠(ObjectPoolFactory)類
該類主要用于管理相同類型和設(shè)置的對象池(ObjectPool),它一般包含如下兩個(gè)方法:
·createPool:用于創(chuàng)建特定類型和設(shè)置的對象池;
·destroyPool:用于釋放指定的對象池;
同時(shí)為保證ObjectPoolFactory的單一實(shí)例,可以采用Singleton設(shè)計(jì)模式,見下述getInstance方法的實(shí)現(xiàn):
2)參數(shù)對象(ParameterObject)類
該類主要用于封裝所創(chuàng)建對象池的一些屬性參數(shù),如池中可存放對象的數(shù)目的最大值(maxCount)、最小值(minCount)等。
3)對象池(ObjectPool)類
用于管理要被池化對象的借出和歸還,并通知PoolableObjectFactory完成相應(yīng)的工作。它一般包含如下兩個(gè)方法:
·getObject:用于從池中借出對象;
·returnObject:將池化對象返回到池中,并通知所有處于等待狀態(tài)的線程;
4)池化對象工廠(PoolableObjectFactory)類
該類主要負(fù)責(zé)管理池化對象的生命周期,就簡單來說,一般包括對象的創(chuàng)建及銷毀。該類同ObjectPoolFactory一樣,也可將其實(shí)現(xiàn)為單實(shí)例。
Java對象的生命周期大致包括三個(gè)階段:對象的創(chuàng)建,對象的使用,對象的清除。因此,對象的生命周期長度可用如下的表達(dá)式表示:T = T1 + T2 +T3。其中T1表示對象的創(chuàng)建時(shí)間,T2表示對象的使用時(shí)間,而T3則表示其清除時(shí)間。由此,我們可以看出,只有T2是真正有效的時(shí)間,而T1、T3則是對象本身的開銷。下面再看看T1、T3在對象的整個(gè)生命周期中所占的比例。
我們知道,Java對象是通過構(gòu)造函數(shù)來創(chuàng)建的,在這一過程中,該構(gòu)造函數(shù)鏈中的所有構(gòu)造函數(shù)也都會(huì)被自動(dòng)調(diào)用。另外,默認(rèn)情況下,調(diào)用類的構(gòu)造函數(shù)時(shí),Java會(huì)把變量初始化成確定的值:所有的對象被設(shè)置成null,整數(shù)變量(byte、short、int、long)設(shè)置成0,float和double變量設(shè)置成0.0,邏輯值設(shè)置成false。所以用new關(guān)鍵字來新建一個(gè)對象的時(shí)間開銷是很大的,如表1所示。
表1 一些操作所耗費(fèi)時(shí)間的對照表
運(yùn)算操作 | 示例 | 標(biāo)準(zhǔn)化時(shí)間 |
本地賦值 | i = n | 1.0 |
實(shí)例賦值 | this.i = n | 1.2 |
方法調(diào)用 | Funct() | 5.9 |
新建對象 | New Object() | 980 |
新建數(shù)組 | New int[10] | 3100 |
從表1可以看出,新建一個(gè)對象需要980個(gè)單位的時(shí)間,是本地賦值時(shí)間的980倍,是方法調(diào)用時(shí)間的166倍,而若新建一個(gè)數(shù)組所花費(fèi)的時(shí)間就更多了。
再看清除對象的過程。我們知道,Java語言的一個(gè)優(yōu)勢,就是Java程序員勿需再像C/C++程序員那樣,顯式地釋放對象,而由稱為垃圾收集器(Garbage Collector)的自動(dòng)內(nèi)存管理系統(tǒng),定時(shí)或在內(nèi)存凸現(xiàn)出不足時(shí),自動(dòng)回收垃圾對象所占的內(nèi)存。凡事有利總也有弊,這雖然為Java程序設(shè)計(jì)者提供了極大的方便,但同時(shí)它也帶來了較大的性能開銷。這種開銷包括兩方面,首先是對象管理開銷,GC為了能夠正確釋放對象,它必須監(jiān)控每一個(gè)對象的運(yùn)行狀態(tài),包括對象的申請、引用、被引用、賦值等。其次,在GC開始回收“垃圾”對象時(shí),系統(tǒng)會(huì)暫停應(yīng)用程序的執(zhí)行,而獨(dú)自占用CPU。
因此,如果要改善應(yīng)用程序的性能,一方面應(yīng)盡量減少創(chuàng)建新對象的次數(shù);同時(shí),還應(yīng)盡量減少T1、T3的時(shí)間,而這些均可以通過對象池技術(shù)來實(shí)現(xiàn)。
對象池技術(shù)的基本原理
對象池技術(shù)基本原理的核心有兩點(diǎn):緩存和共享,即對于那些被頻繁使用的對象,在使用完后,不立即將它們釋放,而是將它們緩存起來,以供后續(xù)的應(yīng)用程序重復(fù)使用,從而減少創(chuàng)建對象和釋放對象的次數(shù),進(jìn)而改善應(yīng)用程序的性能。事實(shí)上,由于對象池技術(shù)將對象限制在一定的數(shù)量,也有效地減少了應(yīng)用程序內(nèi)存上的開銷。
實(shí)現(xiàn)一個(gè)對象池,一般會(huì)涉及到如下的類:
1)對象池工廠(ObjectPoolFactory)類
該類主要用于管理相同類型和設(shè)置的對象池(ObjectPool),它一般包含如下兩個(gè)方法:
·createPool:用于創(chuàng)建特定類型和設(shè)置的對象池;
·destroyPool:用于釋放指定的對象池;
同時(shí)為保證ObjectPoolFactory的單一實(shí)例,可以采用Singleton設(shè)計(jì)模式,見下述getInstance方法的實(shí)現(xiàn):
public static ObjectPoolFactory getInstance() { if (poolFactory == null) { poolFactory = new ObjectPoolFactory(); } return poolFactory; } |
2)參數(shù)對象(ParameterObject)類
該類主要用于封裝所創(chuàng)建對象池的一些屬性參數(shù),如池中可存放對象的數(shù)目的最大值(maxCount)、最小值(minCount)等。
3)對象池(ObjectPool)類
用于管理要被池化對象的借出和歸還,并通知PoolableObjectFactory完成相應(yīng)的工作。它一般包含如下兩個(gè)方法:
·getObject:用于從池中借出對象;
·returnObject:將池化對象返回到池中,并通知所有處于等待狀態(tài)的線程;
4)池化對象工廠(PoolableObjectFactory)類
該類主要負(fù)責(zé)管理池化對象的生命周期,就簡單來說,一般包括對象的創(chuàng)建及銷毀。該類同ObjectPoolFactory一樣,也可將其實(shí)現(xiàn)為單實(shí)例。