聊聊連接池和線程

https://www.cnblogs.com/imyalost/p/7189455.html

一、連接池

1、什麼是連接池?我們爲什麼需要它?

連接池允許多個客戶端使用緩存起來的連接對象,這些對象可以連接數據庫,它們是共享的、可被重複使用的。

打開/關閉數據庫連接開銷很大,連接池技術允許我們在連接池裏維護連接對象,這樣可以提高數據庫的執行命令的性能。多個客戶端請求可以重複使用相同的連接對象,當每次收到一個客戶端請求時,

就會搜索連接池,看看有沒有閒置連接對象。如果沒有,要麼所有的客戶端請求都進入隊列排隊,要麼在池中創建一個新的連接對象(這取決於池裏已有多少個連接存在以及配置支持多少連接)。

一旦某個請求使用完連接對象之後,這個對象會被重新放入池中,然後會被重新分派給排隊等待的請求(分派給哪個請求要看使用什麼調度算法)。

因爲大部分請求都是使用現存的連接對象,所以連接池技術大大減少了等待創建數據庫連接的時間,從而減少了平均連接時間。

2、如何使用連接池?

連接池在基於網絡的企業級應用中很常見,應用服務器負責創建連接對象、添加它們到連接池中,分派連接對象給請求,回收使用完畢的連接對象,重新將它們放回連接池去。

當網絡應用創建數據庫連接時,應用服務器會從池中取出連接對象,而當它使用完畢之後關閉時,應用服務器又負責將使用完的連接對象放回池中。

PS:也可以使用JDBC 1.0/JDBC 2.0 API來獲取物理連接(physical connnection),但這種情況非常少見,因爲數據庫只需要連接一次,不需要連接池的情況。

3、連接池可以處理多少連接?誰創建/釋放連接?

可以進行配置最大的連接數、最小連接數、最大空閒連接數等,所有這些參數都可以由服務器管理員配置。服務器啓動時,固定數量的連接對象(配置的最小連接數)被創建,並添加到連接池中。

當客戶端請求消耗完所有的連接對象時,再有新的請求都會創建新的連接對象,它們被添加到連接池再分派給這個新的請求,直到設置的達到最大的連接數。

服務器也會一直查看閒置的連接對象數,當檢測到閒置的連接數超過設置值時,服務器會關閉閒置連接,然後它們將被垃圾回收。

4、傳統的連接池 vs 可管理的連接池

連接池是個開放的概念,任何應用都可以使用這個概念,並用自己想要的方式管理它。連接池概念指的是創建、管理、維護連接對象。

但當應用的規模增大時,如果沒有一個健壯的連接池機制的話,管理連接是會得越來越困難。

因此,建立一個健壯的、可管理的連接池很有必要。

PS:關於連接池的內容,參考自http://www.importnew.com/8179.html

 

二、線程&線程池,連接&連接池

線程:程序執行流的最小單元,進程中的一個實體,一個相對獨立的、可調度的執行單元,是被系統獨立調度和分派的基本單位;

多線程技術,指在一個進程當中可以創建多個線程來“同時”處理多個事務;

線程池:可以理解爲緩衝區,由於頻繁的創建銷燬線程會帶來一定的成本,可以預先創建,但不立即銷燬,以共享方式爲別人提供服務,一來可以提供效率,再者可以控制線程無線擴張。

連接:指一點與另一點的連接;

連接池:跟線程池有同樣的妙處,但連接池可以是基於多線程來實現,也可以通過多進程來實現,也可能是單實例的。

舉個例子:

Socket在做爲服務時,可以同時監聽多個客戶端連接,那麼它的實現原理就有點像“連接池”;每個客戶通過多個端口同時向服務器發送數據,可以認爲是多線程,

而服務器可能已經建立好了n個線程來等待同時處理/分析客戶端發來的數據,可以爲是有個“線程池”。

 

三、線程的幾種狀態

線程在一定條件下,狀態會發生變化。線程一共有以下幾種狀態:

1、新建狀態(New):新創建了一個線程對象。

2、就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於“可運行線程池”中,變得可運行,只等待獲取CPU的使用權,

   即在就緒狀態的進程除CPU之外,其它的運行所需資源都已全部獲得。

3、運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。

4、阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。

   阻塞的情況分三種:

①.等待阻塞:運行的線程執行wait()方法,該線程會釋放佔用的所有資源,JVM會把該線程放入“等待池”中。進入這個狀態後,是不能自動喚醒的,

   必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒,

②.同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入“鎖池”中。

③.其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時,

   或者I/O處理完畢時,線程重新轉入就緒狀態。

5、死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

   線程變化的狀態轉換圖如下:

PS:拿到對象的鎖標記,即爲獲得了對該對象(臨界區)的使用權限。即該線程獲得了運行所需的資源,進入“就緒狀態”,只需獲得CPU,就可以運行。

    因爲當調用wait()後,線程會釋放掉它所佔有的“鎖標誌”,所以線程只有在此獲取資源才能進入就緒狀態。

下面作下解釋: 

①.線程的實現有兩種方式,一是繼承Thread類,二是實現Runnable接口,但不管怎樣,  當我們new了這個對象後,線程就進入了初始狀態; 

②.當該對象調用了start()方法,就進入就緒狀態; 

③.進入就緒後,當該對象被操作系統選中,獲得CPU時間片就會進入運行狀態; 

④.進入運行狀態後情況就比較複雜;

   (1)run()方法或main()方法結束後,線程就進入終止狀態; 

   (2)當線程調用了自身的sleep()方法或其他線程的join()方法,進程讓出CPU,然後就會進入阻塞狀態(該狀態既停止當前線程,但並不釋放所佔有的資源,

       即調用sleep()函數後,線程不會釋放它的“鎖標誌”。)。當sleep()結束或join()結束後,該線程進入可運行狀態,繼續等待OS分配CPU時間片;

       典型地,sleep()被用在等待某個資源就緒的情形;測試發現條件不滿足後,讓線程阻塞一段時間後重新測試,直到條件滿足爲止。

   (3)線程調用了yield()方法,意思是放棄當前獲得的CPU時間片,回到就緒狀態,這時與其他進程處於同等競爭狀態,OS有可能會接着又讓這個進程進入運行狀態;

       調用 yield() 的效果等價於調度程序認爲該線程已執行了足夠的時間片從而需要轉到另一個線程。yield()只是使當前線程重新回到可執行狀態,

       所以執行yield()的線程有可能在進入到可執行狀態後馬上又被執行。

   (4)當線程剛進入可運行狀態(注意,還沒運行),發現將要調用的資源被synchroniza(同步),獲取不到鎖標記,將會立即進入鎖池狀態,等待獲取鎖標記

      (這時的鎖池裏也許已經有了其他線程在等待獲取鎖標記,這時它們處於隊列狀態,既先到先得),一旦線程獲得鎖標記後,就轉入就緒狀態,等待OS分配CPU時間片。

   (5)suspend() 和 resume()方法:兩個方法配套使用,suspend()使得線程進入阻塞狀態,並且不會自動恢復,必須其對應的resume()被調用,才能使得線程重新進入可執行狀態。

       典型地,suspend()和 resume() 被用在等待另一個線程產生的結果的情形:測試發現結果還沒有產生後,讓線程阻塞,另一個線程產生了結果後,調用resume()使其恢復。 

   (6)wait()和 notify() 方法:當線程調用wait()方法後會進入等待隊列(進入這個狀態會釋放所佔有的所有資源,與阻塞狀態不同),進入這個狀態後,是不能自動喚醒的,

       必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒(由於notify()只是喚醒一個線程,但我們由不能確定具體喚醒的是哪一個線程,也許我們需要喚醒的線程不能夠被喚醒,

       因此在實際使用時,一般都用notifyAll()方法,喚醒有所線程),線程被喚醒後會進入鎖池,等待獲取鎖標記。 

       wait() 使得線程進入阻塞狀態,它有兩種形式:

       一種允許指定以ms爲單位的時間作爲參數,另一種沒有參數。前者當對應的notify()被調用或超出指定時間時線程重新進入可執行狀態即就緒狀態,後者則必須對應的notify()被調用。

       當調用wait()後,線程會釋放掉它所佔有的“鎖標誌”,從而使線程所在對象中的其它synchronized數據可被別的線程使用。

       waite()和notify()因爲會對對象的“鎖標誌”進行操作,所以它們必須在synchronized函數或synchronizedblock中進行調用。

       如果在non-synchronized函數或non-synchronizedblock中進行調用,雖然能編譯通過,但在運行時會發生IllegalMonitorStateException的異常。

PS:關於線程的幾種狀態,轉載自開源中國:線程的幾種狀態

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章