標籤:
(2)對象程池 (2.1)線程池概念
諸如web伺服器、資料庫伺服器、檔案伺服器和郵件伺服器等許多伺服器應用都面向處理來自某些遠程來源的大量短小的任務。構建伺服器應用程式的一個過於簡單的模型是:每當一個請求到達就建立一個新的服務物件,然後在新的服務物件中為請求服務。但當有大量請求並發訪問時,伺服器不斷的建立和銷毀對象的開銷很大。所以提高伺服器效率的一個手段就是儘可能減少建立和銷毀對象的次數,特別是一些很耗資源的對象建立和銷毀,這樣就引入了“池”的概念,“池”的概念使得人們可以定製一定量的資源,然後對這些資源進行複用,而不是頻繁的建立和銷毀。
線程池是預先建立線程的一種技術。線程池在還沒有任務到來之前,建立一定數量的線程,放入空閑隊列中。這些線程都是處於睡眠狀態,即均為啟動,不消耗CPU,而只是佔用較小的記憶體空間。當請求到來之後,緩衝池給這次請求分配一個空閑線程,把請求傳入此線程中運行,進行處理。當預先建立的線程都處於運行狀態,即預製線程不夠,線程池可以自由建立一定數量的新線程,用於處理更多的請求。當系統比較閑的時候,也可以通過移除一部分一直處於停用狀態的線程。
(2.2)線程池作用 線程池作用就是
限制系統中執行線程的數量。根據系統的環境情況,可以自動或手動設定線程數量,達到啟動並執行最佳效果;少了浪費了系統資源,多了造成系統擁擠效率不高。、
如果並發的線程數量很多,並且每個線程都是執行一個時間很短的任務就結束了,這樣頻繁建立線程就會大大降低系統的效率,因為頻繁建立線程和銷毀線程需要時間。
那麼有沒有一種辦法使得線程可以複用,就是執行完一個任務,並不被銷毀,而是可以繼續執行其他的任務?
在Java中可以通過線程池來達到這樣的效果。今天我們就來詳細講解一下Java的線程池,首先我們從最核心的ThreadPoolExecutor類中的方法講起
(2.3)為什麼要用線程池
1.減少了建立和銷毀線程的次數,每個背景工作執行緒都可以被重複利用,可執行多個任務。
個人補充:tomcat處理Http請求也是使用的線程池,如所示
2.可以根據系統的承受能力,調整線程池中工作線線程的數目,防止因為消耗過多的記憶體,而把伺服器累趴下(每個線程需要大約1MB記憶體,線程開的越多,消耗的記憶體也就越大,最後死機)。
Java裡麵線程池的頂級介面是Executor,但是嚴格意義上講Executor並不是一個線程池,而只是一個執行線程的工具。真正的線程池介面是ExecutorService。
(2.4)線程池核心類 比較重要的幾個類:
ExecutorService |
真正的線程池介面。(介面) |
ScheduledExecutorService |
能和Timer/TimerTask類似,解決那些需要任務重複執行的問題。(介面) |
ThreadPoolExecutor |
ExecutorService的預設實現。(實現) |
ScheduledThreadPoolExecutor |
繼承ThreadPoolExecutor的ScheduledExecutorService介面實現,週期性任務調度的類實現。(實現) |
要配置一個線程池是比較複雜的,尤其是對於線程池的原理不是很清楚的情況下,很有可能配置的線程池不是較優的,因此在Executors類裡面提供了一些靜態工廠,產生一些常用的線程池。
1. new SingleThreadExecutor
建立一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當於單線程串列執行所有任務。如果這個唯一的線程因為異常結束,那麼會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。
2.new FixedThreadPool
建立固定大小的線程池。每次提交一個任務就建立一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那麼線程池會補充一個新線程。
3. new CachedThreadPool
建立一個可快取的線程池。如果線程池的大小超過了處理任務所需要的線程,
那麼就會回收部分空閑(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴於作業系統(或者說JVM)能夠建立的最大線程大小。
4.new ScheduledThreadPool
java企業級通用許可權安全架構源碼 SpringMVC mybatis or hibernate+ehcache shiro druid bootstrap HTML5
【java架構源碼下載】
java 對象池