数据库连接池-连接的关闭内幕
???????下面我就想就上面的問題談?wù)勎业囊稽c(diǎn)淺見,請大家批評(píng)指正。
???????大家都知道java語言是一種語言級(jí)的多線程機(jī)制的面向?qū)ο笳Z言。比如說,java的基類object,它就有一些諸如wati(),notify(),notifyall()等線程控制的方法。如果大家學(xué)習(xí)過操作系統(tǒng)的化,我想應(yīng)該知道線程存在同步和異步的問題,解決的方法很多,其中就有“信號(hào)量機(jī)制”實(shí)現(xiàn)線程的同步,java的這種同步機(jī)制與操作系統(tǒng)大同小異。同步機(jī)制是一個(gè)比較復(fù)雜的問題,如果感興趣可以找一本操作系統(tǒng)的書看看。
???????下面簡單介紹一些進(jìn)程和線程的概念:
1.?????????進(jìn)程:
???????進(jìn)程是資源分配和獨(dú)立運(yùn)行的基本單位。進(jìn)程的定義很多,下面列舉一些
??????????進(jìn)程是程序的一次執(zhí)行;
??????????進(jìn)程是可以和別的計(jì)算機(jī)并發(fā)執(zhí)行的計(jì)算;
??????????進(jìn)程可定義為一個(gè)數(shù)據(jù)結(jié)構(gòu)及能在其上進(jìn)行操作的一個(gè)程序
??????????進(jìn)程是一個(gè)程序及其數(shù)據(jù)在處理機(jī)上順序執(zhí)行時(shí)發(fā)生的活動(dòng);
??????????進(jìn)程時(shí)程序在一個(gè)數(shù)據(jù)集合上的運(yùn)行過程,時(shí)系統(tǒng)進(jìn)行資源分配和調(diào)度的一個(gè)獨(dú)立單位。
2.?????????線程
由于進(jìn)程是一個(gè)資源擁有者,因而在進(jìn)程的創(chuàng)建、撤消和切換過程中,系統(tǒng)必須為之付出較大的時(shí)空開銷。也正因?yàn)槿绱?#xff0c;在系統(tǒng)中所設(shè)置的進(jìn)程數(shù)目不宜過多,進(jìn)程切換的頻率也不宜過高,但這也就限制了并發(fā)程度的進(jìn)一步提高。因此便引出了線程的概念
把線程作為調(diào)度和分派的基本單位,而把進(jìn)程作為資源擁有的基本單位,使傳統(tǒng)進(jìn)程的兩個(gè)屬性分開,線程便能輕裝運(yùn)行,從而顯著提高系統(tǒng)的并發(fā)程度。
??????????在同一個(gè)進(jìn)程內(nèi)可以有多個(gè)線程;
??????????同一個(gè)進(jìn)程內(nèi)的線程切換不會(huì)引起進(jìn)程切換;
??????????一個(gè)進(jìn)程的線程切換到另一個(gè)進(jìn)程的線程時(shí)會(huì)引起進(jìn)程切換
3.?????????JSP/SERVLET
而我們常用的jsp/ervlet這種j2ee的體系結(jié)構(gòu)正是建立在java的多線程機(jī)制之上的。JSP/SERVLET容器會(huì)自動(dòng)使用線程池等技術(shù)來支持系統(tǒng)的運(yùn)行。因此,JSP/SERVLET的實(shí)質(zhì)是一種線程技術(shù),JSP會(huì)在運(yùn)行時(shí)被編譯成servlet來運(yùn)行,如圖所示:
???????當(dāng)客戶端向服務(wù)器發(fā)出一個(gè)請求時(shí),servlet容器會(huì)分配一個(gè)線程專門處理這個(gè)請求,線程內(nèi)容就是JSP/servlet應(yīng)用程序。
???????這部分內(nèi)容與本主體無關(guān),只是順便說說。
4.?????????線程池
???????首先介紹一下線程池:
???????線程的創(chuàng)建和銷毀,以及切換,執(zhí)行都是要耗費(fèi)系統(tǒng)資源的。當(dāng)系統(tǒng)訪問量比較大的時(shí)候,服務(wù)器內(nèi)就會(huì)創(chuàng)建太多的線程,直至資源完全消耗,這對于應(yīng)用系統(tǒng)的正常運(yùn)行是有致命傷害的。
???????為了能夠在訪問尖峰時(shí)限制活動(dòng)線程的數(shù)量,同時(shí)減少線程頻繁創(chuàng)建和銷毀帶來的系統(tǒng)開銷,提高系統(tǒng)的大訪問量的處理性能和速度,需要事先創(chuàng)建一定數(shù)量的線程供調(diào)用者循環(huán)反復(fù)使用,這就是“池”技術(shù)。
???????線程的基本原理是基于隊(duì)列queue這種數(shù)據(jù)結(jié)構(gòu)的,通過不斷查詢隊(duì)列queue是否有可以運(yùn)行的線程。如果有,就立即運(yùn)行線程,沒有,則鎖定等待,直到有新的線程加入被解鎖。(這種鎖定機(jī)制,就是所謂的“信號(hào)量機(jī)制”)。
???????一種線程池必須解決如下的問題:死鎖、資源不足、并發(fā)錯(cuò)誤、線程泄漏和請求過載。下面我們具體舉一個(gè)成熟的開源線程池的例子來說明線程池的原理:
????PooledExecutor?pool=new?PooledExecutor(new?BoundedBuffer(20),100);
????pool.setMinimumPoolSize(10);//最小線程數(shù)為10
????poole.setKeepAliveTime(-1);//線程一直運(yùn)行
????上面的語句設(shè)置了線程的最大數(shù)目為100,這樣,就可以保護(hù)系統(tǒng)不會(huì)因?yàn)樵L問量增加導(dǎo)致線程數(shù)目的無限增加。使用該線程池如下:
???????pool.execute(java.lang.Runnable?自己的線程);
???????這一句實(shí)際上是將“自己的線程”加入一個(gè)隊(duì)列中,而隊(duì)列(先進(jìn)先出FIFO)另一段正開啟多個(gè)線程不斷讀取這個(gè)隊(duì)列,一旦隊(duì)列中有空閑的線程,線程管理器就將讀取并分配線程來運(yùn)行它。
? ? ??
????public?void?execute(Runnable?command)?throws?InterruptedException?{
???????for?(;;)?{?//一直循環(huán)
???????????synchronized?(this)?{
??????????????if?(!shutdown_)?{?//確保線程池沒有關(guān)閉
??????????????????int?size?=?poolSize_;?//當(dāng)前線程池中線程的數(shù)目
??????????????????if?(size?<?minimumPoolSize_)?{?//如果當(dāng)前線程數(shù)目少于線程池最小數(shù)目
?????????????????????addThread(command);
?????????????????????return;
??????????????????}
??????????????????//如果目前線程池中有超過或等于最小數(shù)目的線程
??????????????????//分配一個(gè)存在的空閑線程來運(yùn)行command,handOff是隊(duì)列
??????????????????if?(handOff_.offer(command,?0))?{
?????????????????????return;
??????????????????}
??????????????????//如果不能分配已有的線程來運(yùn)行command,那么創(chuàng)建一個(gè)新線程
??????????????????if?(size?<?maximumPoolSize_)?{
?????????????????????addThread(command);
?????????????????????return;
??????????????????}
??????????????}
???????????}
???????????//如果阻塞,則請求幫助
???????????if?(getBlockedExecutionHandler().bolckedAction(command))?{
??????????????return;
???????????}
???????}
????}
???????由上面的代碼可見,PooledExecutor線程池的原理是,當(dāng)執(zhí)行execute加載一個(gè)應(yīng)用系統(tǒng)的線程時(shí),線程池內(nèi)部首先檢查當(dāng)前線程數(shù)目是否達(dá)到設(shè)定的最小數(shù)目。如果沒有達(dá)到,啟動(dòng)新線程運(yùn)行;如果達(dá)到了,那么檢查有無空閑線程可用;如果沒有空閑的,則創(chuàng)建新線程,直到達(dá)到最大數(shù)目。
???????使用線程池的好處是:首先是循環(huán)使用,一經(jīng)創(chuàng)建后,空閑的線程可以被反復(fù)使用,提高了運(yùn)行效率;其次有最大數(shù)目的限制,保證了系統(tǒng)的安全性。
5.?????????連接池
終于輪到連接池了,通過上面的介紹,我們對線程及線程池都有個(gè)一個(gè)大致的了解。
在正常情況下,直接使用JDBC調(diào)用數(shù)據(jù)庫可以滿足一個(gè)小型系統(tǒng)的要求,但是當(dāng)系統(tǒng)規(guī)模比較大的情況下,就會(huì)出現(xiàn)數(shù)據(jù)庫的訪問量迅速提升而令服務(wù)器不堪重負(fù)的現(xiàn)象,因而為了解決這一性能問題,常常會(huì)使用數(shù)據(jù)庫連接池作為一個(gè)緩存的方式解決。
連接池類似上面介紹的線程池。
每次數(shù)據(jù)庫連接的建立都需要花費(fèi)一定的時(shí)空費(fèi)用,而使用連接池,可以事先建立連接。當(dāng)應(yīng)用程序需要開始使用時(shí),就從連接池中獲取一個(gè)連接使用,應(yīng)用程序使用完畢,通過close()方法將連接歸還連接池。講到這里,我門就不必在擔(dān)心close()方法會(huì)不會(huì)影響性能了,完全可以放心大膽的使用。因?yàn)?#xff0c;它實(shí)際上并沒有關(guān)閉連接,而是將連接歸還連接池,供下次使用。
當(dāng)并發(fā)增加是,連接池會(huì)不斷的自動(dòng)創(chuàng)建新的連接滿足調(diào)用,直到達(dá)到連接池的最大數(shù)目;當(dāng)連接池連接減少甚至沒有時(shí),連接池自動(dòng)關(guān)閉一些連接,保持最小數(shù)目。
因此連接池的使用節(jié)省了連接建立時(shí)間,消除了數(shù)據(jù)庫頻繁連接帶來的開銷和瓶頸。
小提示:不知道大家有沒有注意到配置websphere時(shí)有關(guān)于連接池最大最小數(shù)目的配置。呵呵,道理就在這。
那么,我們經(jīng)常面對的連接未關(guān)閉的問題導(dǎo)致的系統(tǒng)速度很慢的問題就很容易說明了,就是因?yàn)榫€程池已經(jīng)達(dá)到了最大數(shù)目,沒有可用的了。所以,其他操作只有等待的份,等待那些應(yīng)用用完了,被垃圾回收了,才能釋放出可用的連接。?
總結(jié)
以上是生活随笔為你收集整理的数据库连接池-连接的关闭内幕的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wpf资源嵌套,一个资源引用另外一个资源
- 下一篇: [MySQL]--gt;查询5天之内过生