標籤:
系統啟動一個新的線程的成本是比較高的,因為它涉及到了有作業系統的互動,當程式性要建立大量生存期很短暫的線程時,更應該考慮使用線程池。
線程池在啟動時即建立了大量的閒置線程,可以指定線程的數量,但一個Runnable對象傳給線程池是,線程池就會啟動一個線程來執行它們的run()方法。當run()方法執行完畢時,該線程並不會死亡,而是再次返回線程池中成為空白閑狀態。等待執行下一個Runnable對象的run()方法
線程池可以設定最大的並發線程數。
1、new Thread 的弊端
執行一個非同步任務如果是new Thread:
new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stub}}).start();
這樣會有如下的弊端:
a.每次new Thread 建立對象的效能差
b. 線程缺乏統一管理,可能無限制建立線程,相互之間競爭,及可能佔用過多系統資源導致死機
c.缺乏更多功能,如定時執行,定期執行、線程中斷
相比new Thread ,java 提供的四種線程池的好處在於:
a.重用存在的線程,減少對象的建立、消亡的開銷,效能佳,減少CPU在建立、消除的開銷。
比如:
假設在一台伺服器完成一項任務的時間為T
T1 建立線程的時間
T2 線上程中執行任務的時間,包括線程間同步所需時間
T3 線程銷毀的時間
顯然T = T1+T2+T3。注意這是一個極度簡化的假設。
可以看出T1,T3是多線程本身的帶來的開銷,我們渴望減少T1,T3所用的時間,從而減少T的時間。但一些線程的使用者並沒有注意到這一點,所以在程式中頻繁的建立或銷毀線程,這導致T1和T3在T中佔有相當比例。顯然這是突出了線程的弱點(T1,T3),而不是優點(並發性)。
b.可有效控制最大並發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免阻塞
c.提供定時執行、定期執行、單線程、並發數控制等功能。
在Android中當同時並發多個網路線程時,引入線程池技術會極大地提高APP的效能
2、java 線程池
java 中有內建線程池 有兩種線程池對象 ExecutorService----表示儘快執行線程的線程池(只要線程池中有空閑線程,就立即執行線程任務)、ScheduledExecutorService(scheduled 表示可以延遲後執行,是ExecutorService的子類)
newCachedThreadPool建立一個可緩衝線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則建立線程。
newFixedThreadPool 建立一個定長線程池,可控制線程最大並發數,超出的線程會在隊列中等待。
newScheduledThreadPool 建立一個定長線程池,支援定時及週期性任務執行。參數表示儲存的線程數,即使線程是閒置也被儲存線上程池中。
newSingleThreadExecutor 建立一個單線程化的線程池,它只會用唯一的背景工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
使用線程池
JDK自身帶有線程池的實作類別ThreadPoolExecutor
ExecutorService 提供了三個方法
1、Future<?> submit(Runnable task) 將一個Runnable 對象提交給指定的線程池,線程池將在有空閑線程是執行Runnable對象代表的任務,其中Future對象代表Runnable任務的傳回值--但是run()方法執行結束後返回Null ,但可以調用Future的isDone()、isCancelled()方法來獲得Runnable對象的執行狀態。
2、<T>Future<T> submit(Runnable task,T result) 將一個Runnable 對象提交給指定的線程池,線程池將在有空閑線程是執行Runnable對象代表的任務,其中Future對象代表Runnable任務的傳回值--可以指定顯示的傳回值,result為線程執行結束後的傳回值。
ScheduledExecutorService 代表可在指定延遲後或周期性地執行線程任務的線程池。
1、ScheduledFuture<V> schedule(Runnable command ,long delay,TimeUnit unit)
指定command 任務將在delay延遲後執行。
2、ScheduledFuture<V> scheduleAtFixedRate(Runnable command ,long delay,long period,TimeUnit unit) 指定command 任務將在delay延遲後執行。並設定頻率重複執行,也就是在delay+period、delay+2*period.........(重複執行)
用完一個線程池後,應該調用該線程池的shutdown()方法,該方法將啟動線程池的關閉序列,調用該方法後的線程池不再接收新任務,但會將以前所有已提交任務執行完畢。但線程池中的所有任務都執行完成後,池中的所有線程都會死亡。
java(Android)線程池