Java 四種線程池的用法分析

1、new Thread的弊端

執(zhí)行一個異步任務你還只是如下new Thread嗎晴弃?

```

new Thread(new Runnable() {

@Override

public void run() {

// TODO Auto-generated method stub

}

}

).start();

```

那你就out太多了掩幢,new Thread的弊端如下:

a. 每次new Thread新建對象性能差。

b. 線程缺乏統(tǒng)一管理上鞠,可能無限制新建線程际邻,相互之間競爭,及可能占用過多系統(tǒng)資源導致死機或oom芍阎。

c. 缺乏更多功能世曾,如定時執(zhí)行、定期執(zhí)行谴咸、線程中斷轮听。

相比new Thread骗露,Java提供的四種線程池的好處在于:

a. 重用存在的線程,減少對象創(chuàng)建血巍、消亡的開銷萧锉,性能佳。

b. 可有效控制最大并發(fā)線程數(shù)藻茂,提高系統(tǒng)資源的使用率驹暑,同時避免過多資源競爭,避免堵塞辨赐。

c. 提供定時執(zhí)行、定期執(zhí)行京办、單線程掀序、并發(fā)數(shù)控制等功能。

2惭婿、Java 線程池

Java通過Executors提供四種線程池不恭,分別為:

newCachedThreadPool創(chuàng)建一個可緩存線程池,如果線程池長度超過處理需要财饥,可靈活回收空閑線程换吧,若無可回收,則新建線程钥星。

newFixedThreadPool 創(chuàng)建一個定長線程池沾瓦,可控制線程最大并發(fā)數(shù),超出的線程會在隊列中等待谦炒。

newScheduledThreadPool 創(chuàng)建一個定長線程池贯莺,支持定時及周期性任務執(zhí)行襟衰。

newSingleThreadExecutor 創(chuàng)建一個單線程化的線程池票唆,它只會用唯一的工作線程來執(zhí)行任務,保證所有任務按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行唆铐。

(1)newCachedThreadPool:

創(chuàng)建一個可緩存線程池还蹲,如果線程池長度超過處理需要爹耗,可靈活回收空閑線程,若無可回收谜喊,則新建線程潭兽。示例代碼如下:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

for (int i = 0; i < 10; i++) {

final int index = i;

try {

Thread.sleep(index * 1000);

}

catch (InterruptedException e) {

e.printStackTrace();

}

cachedThreadPool.execute(new Runnable() {

@Override

public void run() {

System.out.println(index);

}

});

}

線程池為無限大,當執(zhí)行第二個任務時第一個任務已經(jīng)完成锅论,會復用執(zhí)行第一個任務的線程讼溺,而不用每次新建線程。

(2)newFixedThreadPool:

創(chuàng)建一個定長線程池最易,可控制線程最大并發(fā)數(shù)怒坯,超出的線程會在隊列中等待炫狱。示例代碼如下:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);

for (int i = 0; i < 10; i++) {

final int index = i;

fixedThreadPool.execute(new Runnable() {

@Override

public void run() {

try {

System.out.println(index);

Thread.sleep(2000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

});

}

因為線程池大小為3,每個任務輸出index后sleep 2秒剔猿,所以每兩秒打印3個數(shù)字视译。

定長線程池的大小最好根據(jù)系統(tǒng)資源進行設置。如Runtime.getRuntime().availableProcessors()归敬】岷可參考PreloadDataCache。

(3)newScheduledThreadPool:

創(chuàng)建一個定長線程池汪茧,支持定時及周期性任務執(zhí)行椅亚。延遲執(zhí)行示例代碼如下:

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);

scheduledThreadPool.schedule(new Runnable() {

@Override

public void run() {

System.out.println("delay 3 seconds");

}

}, 3, TimeUnit.SECONDS);

表示延遲3秒執(zhí)行。

定期執(zhí)行示例代碼如下:

scheduledThreadPool.scheduleAtFixedRate(new Runnable() {

@Override

public void run() {

System.out.println("delay 1 seconds, and excute every 3 seconds");

}

}, 1, 3, TimeUnit.SECONDS);

表示延遲1秒后每3秒執(zhí)行一次舱污。

ScheduledExecutorService比Timer更安全呀舔,功能更強大

(4)newSingleThreadExecutor:

創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務扩灯,保證所有任務按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行媚赖。示例代碼如下:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

for (int i = 0; i < 10; i++) {

final int index = i;

singleThreadExecutor.execute(new Runnable() {

@Override

public void run() {

try {

System.out.println(index);

Thread.sleep(2000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

});

}

結(jié)果依次輸出,相當于順序執(zhí)行各個任務珠插。

現(xiàn)行大多數(shù)GUI程序都是單線程的惧磺。Android中單線程可用于數(shù)據(jù)庫操作,文件操作捻撑,應用批量安裝磨隘,應用批量刪除等不適合并發(fā)但可能IO阻塞性及影響UI線程響應的操作。

線程池的作用:

線程池作用就是限制系統(tǒng)中執(zhí)行線程的數(shù)量布讹。

根 據(jù)系統(tǒng)的環(huán)境情況琳拭,可以自動或手動設置線程數(shù)量,達到運行的最佳效果描验;少了浪費了系統(tǒng)資源白嘁,多了造成系統(tǒng)擁擠效率不高。用線程池控制線程數(shù)量膘流,其他線程排 隊等候絮缅。一個任務執(zhí)行完畢,再從隊列的中取最前面的任務開始執(zhí)行呼股。若隊列中沒有等待進程耕魄,線程池的這一資源處于等待。當一個新任務需要運行時彭谁,如果線程池 中有等待的工作線程吸奴,就可以開始運行了;否則進入等待隊列。

為什么要用線程池:

1.減少了創(chuàng)建和銷毀線程的次數(shù)则奥,每個工作線程都可以被重復利用考润,可執(zhí)行多個任務。

2.可以根據(jù)系統(tǒng)的承受能力读处,調(diào)整線程池中工作線線程的數(shù)目糊治,防止因為消耗過多的內(nèi)存,而把服務器累趴下(每個線程需要大約1MB內(nèi)存罚舱,線程開的越多井辜,消耗的內(nèi)存也就越大,最后死機)管闷。

Java里面線程池的頂級接口是Executor粥脚,但是嚴格意義上講Executor并不是一個線程池,而只是一個執(zhí)行線程的工具包个。真正的線程池接口是ExecutorService阿逃。

比較重要的幾個類:

ExecutorService: 真正的線程池接口。

ScheduledExecutorService: 能和Timer/TimerTask類似赃蛛,解決那些需要任務重復執(zhí)行的問題。

ThreadPoolExecutor: ExecutorService的默認實現(xiàn)搀菩。

ScheduledThreadPoolExecutor: 繼承ThreadPoolExecutor的ScheduledExecutorService接口實現(xiàn)呕臂,周期性任務調(diào)度的類實現(xiàn)。

要配置一個線程池是比較復雜的肪跋,尤其是對于線程池的原理不是很清楚的情況下歧蒋,很有可能配置的線程池不是較優(yōu)的,因此在Executors類里面提供了一些靜態(tài)工廠州既,生成一些常用的線程池谜洽。

1.newSingleThreadExecutor

創(chuàng)建一個單線程的線程池。這個線程池只有一個線程在工作吴叶,也就是相當于單線程串行執(zhí)行所有任務阐虚。如果這個唯一的線程因為異常結(jié)束,那么會有一個新的線程來替代它蚌卤。此線程池保證所有任務的執(zhí)行順序按照任務的提交順序執(zhí)行实束。

2.newFixedThreadPool

創(chuàng)建固定大小的線程池。每次提交一個任務就創(chuàng)建一個線程逊彭,直到線程達到線程池的最大大小咸灿。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執(zhí)行異常而結(jié)束侮叮,那么線程池會補充一個新線程避矢。

3.newCachedThreadPool

創(chuàng)建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,

那么就會回收部分空閑(60秒不執(zhí)行任務)的線程审胸,當任務數(shù)增加時亥宿,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制歹嘹,線程池大小完全依賴于操作系統(tǒng)(或者說JVM)能夠創(chuàng)建的最大線程大小箩绍。

4.newScheduledThreadPool

創(chuàng)建一個大小無限的線程池。此線程池支持定時以及周期性執(zhí)行任務的需求尺上。

實例代碼

一材蛛、固定大小的線程池,newFixedThreadPool:

package app.executors;

import java.util.concurrent.Executors;

import java.util.concurrent.ExecutorService;

/**

* Java線程:線程池

*

* @author xiho

*/

public class Test {

public static void main(String[] args) {

// 創(chuàng)建一個可重用固定線程數(shù)的線程池

ExecutorService pool = Executors.newFixedThreadPool(2);

// 創(chuàng)建線程

Thread t1 = new MyThread();

Thread t2 = new MyThread();

Thread t3 = new MyThread();

Thread t4 = new MyThread();

Thread t5 = new MyThread();

// 將線程放入池中進行執(zhí)行

pool.execute(t1);

pool.execute(t2);

pool.execute(t3);

pool.execute(t4);

pool.execute(t5);

// 關(guān)閉線程池

pool.shutdown();

}

}

class MyThread extends Thread {

@Override

public void run() {

System.out.println(Thread.currentThread().getName() + "正在執(zhí)行怎抛。卑吭。。");

}

}

輸出結(jié)果:

pool-1-thread-1正在執(zhí)行马绝。豆赏。。

pool-1-thread-3正在執(zhí)行富稻。掷邦。。

pool-1-thread-4正在執(zhí)行椭赋。抚岗。。

pool-1-thread-2正在執(zhí)行哪怔。宣蔚。。

pool-1-thread-5正在執(zhí)行认境。胚委。。

改變ExecutorService pool = Executors.newFixedThreadPool(5)中的參數(shù):ExecutorService pool = Executors.newFixedThreadPool(2)叉信,輸出結(jié)果是:

pool-1-thread-1正在執(zhí)行亩冬。。茉盏。

pool-1-thread-1正在執(zhí)行鉴未。。鸠姨。

pool-1-thread-2正在執(zhí)行铜秆。。讶迁。

pool-1-thread-1正在執(zhí)行连茧。。。

pool-1-thread-2正在執(zhí)行啸驯。客扎。。

從以上結(jié)果可以看出罚斗,newFixedThreadPool的參數(shù)指定了可以運行的線程的最大數(shù)目徙鱼,超過這個數(shù)目的線程加進去以后,不會運行针姿。其次袱吆,加入線程池的線程屬于托管狀態(tài),線程的運行不受加入順序的影響距淫。

二绞绒、單任務線程池,newSingleThreadExecutor:

僅僅是把上述代碼中的ExecutorService pool = Executors.newFixedThreadPool(2)改為ExecutorService pool = Executors.newSingleThreadExecutor();

輸出結(jié)果:

pool-1-thread-1正在執(zhí)行榕暇。蓬衡。。

pool-1-thread-1正在執(zhí)行彤枢。狰晚。。

pool-1-thread-1正在執(zhí)行缴啡。家肯。。

pool-1-thread-1正在執(zhí)行盟猖。。换棚。

pool-1-thread-1正在執(zhí)行式镐。。固蚤。

可以看出娘汞,每次調(diào)用execute方法,其實最后都是調(diào)用了thread-1的run方法夕玩。

三你弦、可變尺寸的線程池,newCachedThreadPool:

與上面的類似燎孟,只是改動下pool的創(chuàng)建方式:ExecutorService pool = Executors.newCachedThreadPool();

輸出結(jié)果:

pool-1-thread-1正在執(zhí)行禽作。。揩页。

pool-1-thread-2正在執(zhí)行旷偿。。。

pool-1-thread-4正在執(zhí)行萍程。幢妄。。

pool-1-thread-3正在執(zhí)行茫负。蕉鸳。。

pool-1-thread-5正在執(zhí)行忍法。潮尝。。

這種方式的特點是:可根據(jù)需要創(chuàng)建新線程的線程池缔赠,但是在以前構(gòu)造的線程可用時將重用它們衍锚。

四、延遲連接池嗤堰,newScheduledThreadPool:

public class TestScheduledThreadPoolExecutor {

public static void main(String[] args) {

ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);

exec.scheduleAtFixedRate(new Runnable() {//每隔一段時間就觸發(fā)異常

@Override

publicvoid run() {

//throw new RuntimeException();

System.out.println("================");

}

}, 1000, 5000, TimeUnit.MILLISECONDS);

exec.scheduleAtFixedRate(new Runnable() {//每隔一段時間打印系統(tǒng)時間戴质,證明兩者是互不影響的

@Override

publicvoid run() {

System.out.println(System.nanoTime());

}

}, 1000, 2000, TimeUnit.MILLISECONDS);

}

}

輸出結(jié)果:

================

8384644549516

8386643829034

8388643830710

================

8390643851383

8392643879319

8400643939383

轉(zhuǎn)載地址:http://www.codeceo.com/article/java-4-threadpool.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市踢匣,隨后出現(xiàn)的幾起案子告匠,更是在濱河造成了極大的恐慌,老刑警劉巖离唬,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件后专,死亡現(xiàn)場離奇詭異,居然都是意外死亡输莺,警方通過查閱死者的電腦和手機戚哎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫂用,“玉大人型凳,你說我怎么就攤上這事≈龊” “怎么了甘畅?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長往弓。 經(jīng)常有香客問我疏唾,道長,這世上最難降的妖魔是什么函似? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任槐脏,我火速辦了婚禮,結(jié)果婚禮上撇寞,老公的妹妹穿的比我還像新娘准给。我一直安慰自己泄朴,他們只是感情好,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布露氮。 她就那樣靜靜地躺著祖灰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪畔规。 梳的紋絲不亂的頭發(fā)上局扶,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音叁扫,去河邊找鬼三妈。 笑死,一個胖子當著我的面吹牛莫绣,可吹牛的內(nèi)容都是我干的畴蒲。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼对室,長吁一口氣:“原來是場噩夢啊……” “哼模燥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起掩宜,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤蔫骂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后牺汤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辽旋,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年檐迟,在試婚紗的時候發(fā)現(xiàn)自己被綠了补胚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡追迟,死狀恐怖糖儡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情怔匣,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布桦沉,位于F島的核電站每瞒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏纯露。R本人自食惡果不足惜剿骨,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望埠褪。 院中可真熱鬧浓利,春花似錦挤庇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至苹威,卻和暖如春昆咽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背牙甫。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工掷酗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窟哺。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓泻轰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親且轨。 傳聞我的和親對象是個殘疾皇子浮声,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 前段時間遇到這樣一個問題,有人問微信朋友圈的上傳圖片的功能怎么做才能讓用戶的等待時間較短殖告,比如說一下上傳9張圖片,...
    加油碼農(nóng)閱讀 1,183評論 0 2
  • 一.線程與進程相關(guān) 1.進程 ??定義:進程是具有獨立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運行活動阿蝶,進程是操作系統(tǒng)分...
    Geeks_Liu閱讀 1,707評論 2 4
  • 線程池的基本思想還是一種對象池的思想,開辟一塊內(nèi)存空間黄绩,里面存放了眾多(未死亡)的線程羡洁,池中線程執(zhí)行調(diào)度由池管理器...
    Arya鑫閱讀 6,663評論 0 5
  • 系統(tǒng)啟動一個新線程的成本是比較高的筑煮,因為它涉及到與操作系統(tǒng)的交互。在這種情況下粤蝎,使用線程池可以很好的提供性能真仲,尤其...
    我是嘻哈大哥閱讀 408評論 0 2
  • 內(nèi)心的什么已經(jīng)枯竭 慢慢地枯萎 就像一朵花 已經(jīng)開過啦 也許又開過啦 但還會再開 只不過不會再是同一朵 也許不會再...
    春少邪閱讀 262評論 0 2