一、介紹
線程池是一種多線程處理形式,處理過程中將任務(wù)添加到隊(duì)列,然后在創(chuàng)建線程后自動(dòng)啟動(dòng)這些任務(wù)。線程池線程都是后臺(tái)線程。每個(gè)線程都使用默認(rèn)的堆棧大小,以默認(rèn)的優(yōu)先級(jí)運(yùn)行,并處于多線程單元中。如果某個(gè)線程在托管代碼中空閑(如正在等待某個(gè)事件),則線程池將插入另一個(gè)輔助線程來使所有處理器保持繁忙。如果所有線程池線程都始終保持繁忙,但隊(duì)列中包含掛起的工作,則線程池將在一段時(shí)間后創(chuàng)建另一個(gè)輔助線程但線程的數(shù)目永遠(yuǎn)不會(huì)超過最大值。超過最大值的線程可以排隊(duì),但他們要等到其他線程完成后才啟動(dòng)。
二、作用
1,減少線程創(chuàng)建和銷毀的次數(shù),使每個(gè)工作線程都可以重復(fù)利用。
2,可以手動(dòng)控制線程的數(shù)量,防止因?yàn)榫€程啟動(dòng)的過多使用系統(tǒng)超過負(fù)荷。
三、類的層級(jí)結(jié)構(gòu)

1,Executor 結(jié)構(gòu)定義了一個(gè)方法來執(zhí)行執(zhí)行任務(wù)。2,ExecutorService定義了完成的線程池的行為,可以接受提交任務(wù)、執(zhí)行任務(wù)、關(guān)閉服務(wù)。3,AbstractExecutorService實(shí)現(xiàn)了ExecutorService接口,也實(shí)現(xiàn)了接口定義的默認(rèn)行為。4,ThreadPool|Executor實(shí)現(xiàn)了ExecutorService接口的全部默認(rèn)行為。四、幾個(gè)常用的線程池
要配置一個(gè)線程池是比較復(fù)雜的,尤其是對(duì)于線程池的原理不是很清楚的情況下,很有可能配置的線程池不是較優(yōu)的,因此在Executors類里面提供了一些靜態(tài)工廠,生成一些常用的線程池。1,newSingleThreadExecutor創(chuàng)建一個(gè)單線程的線程池。這個(gè)線程池只有一個(gè)線程在工作,也就是相當(dāng)于單線程串行執(zhí)行所有任務(wù)。如果這個(gè)唯一的線程因?yàn)楫惓=Y(jié)束,那么會(huì)有一個(gè)新的線程來替代它。此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行。2,newFixedThreadPool創(chuàng)建固定大小的線程池。每次提交一個(gè)任務(wù)就創(chuàng)建一個(gè)線程,直到線程達(dá)到線程池的最大大小。線程池的大小一旦達(dá)到最大值就會(huì)保持不變,如果某個(gè)線程因?yàn)閳?zhí)行異常而結(jié)束,那么線程池會(huì)補(bǔ)充一個(gè)新線程。3,newCachedThreadPool創(chuàng)建一個(gè)可緩存的線程池。如果線程池的大小超過了處理任務(wù)所需要的線程,那么就會(huì)回收部分空閑(60秒不執(zhí)行任務(wù))的線程,當(dāng)任務(wù)數(shù)增加時(shí),此線程池又可以智能的添加新線程來處理任務(wù)。此線程池不會(huì)對(duì)線程池大小做限制,線程池大小完全依賴于操作系統(tǒng)(或者說JVM)能夠創(chuàng)建的最大線程大小。4,newScheduledThreadPool創(chuàng)建一個(gè)大小無限的線程池。此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。
下面看看如何使用:
public class TestA { class MyThread extends Thread { String name; public MyThread(String name){ this.name = name; } @Override public void run() { System.out.PRintln(name+":"+Thread.currentThread().getName()); } } private void createThreadPool() { Thread t1 = new MyThread("第一個(gè)"); Thread t2 = new MyThread("第二個(gè)"); Thread t3 = new MyThread("第三個(gè)"); Thread t4 = new MyThread("第四個(gè)"); Thread t5 = new MyThread("第五個(gè)"); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); } public void threadPool() { createThreadPool(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }}輸出:
第一個(gè):Thread-0第二個(gè):Thread-1第五個(gè):Thread-4第四個(gè):Thread-3第三個(gè):Thread-2分別開了5個(gè)不同的線程去執(zhí)行不同的任務(wù)。1,newSingleThreadExecutor:
private void createThreadPool() { Thread t1 = new MyThread("第一個(gè)"); Thread t2 = new MyThread("第二個(gè)"); Thread t3 = new MyThread("第三個(gè)"); Thread t4 = new MyThread("第四個(gè)"); Thread t5 = new MyThread("第五個(gè)"); ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.execute(t1); executorService.execute(t2); executorService.execute(t3); executorService.execute(t4); executorService.execute(t5); executorService.shutdown(); }輸出:第一個(gè):pool-1-thread-1第二個(gè):pool-1-thread-1第三個(gè):pool-1-thread-1第四個(gè):pool-1-thread-1第五個(gè):pool-1-thread-1它能保證所有的任務(wù)都在同一個(gè)線程中執(zhí)行,而且所有的任務(wù)都順序執(zhí)行。
2,newFixedThreadPool
private void createThreadPool() { Thread t1 = new MyThread("第一個(gè)"); Thread t2 = new MyThread("第二個(gè)"); Thread t3 = new MyThread("第三個(gè)"); Thread t4 = new MyThread("第四個(gè)"); Thread t5 = new MyThread("第五個(gè)"); ExecutorService executorService = Executors.newFixedThreadPool(2); executorService.execute(t1); executorService.execute(t2); executorService.execute(t3); executorService.execute(t4); executorService.execute(t5); executorService.shutdown(); }輸出:第一個(gè):pool-1-thread-1第三個(gè):pool-1-thread-1第二個(gè):pool-1-thread-2第四個(gè):pool-1-thread-1第五個(gè):pool-1-thread-1能保證任務(wù)都在2個(gè)工作線程中執(zhí)行,但是不能保證任務(wù)的執(zhí)行順序。3,newCachedThreadPool, private void createThreadPool() { Thread t1 = new MyThread("第一個(gè)"); Thread t2 = new MyThread("第二個(gè)"); Thread t3 = new MyThread("第三個(gè)"); Thread t4 = new MyThread("第四個(gè)"); Thread t5 = new MyThread("第五個(gè)"); ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(t1); executorService.execute(t2); executorService.execute(t3); executorService.execute(t4); executorService.execute(t5); executorService.shutdown(); }輸出:第二個(gè):pool-1-thread-2第一個(gè):pool-1-thread-1第四個(gè):pool-1-thread-2第三個(gè):pool-1-thread-3第五個(gè):pool-1-thread-44,newScheduledThreadPool
private void createThreadPool() { ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); executorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("---------------------------"); } },500,1000, TimeUnit.MICROSECONDS); executorService.scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println(System.currentTimeMillis()+":"+Thread.currentThread().getName()); } },500,1000, TimeUnit.MICROSECONDS); }輸出:---------------------------1488523824853:pool-1-thread-1---------------------------1488523824853:pool-1-thread-1---------------------------1488523824855:pool-1-thread-1---------------------------1488523824855:pool-1-thread-1五、常用的API1,submit,execute
private void createThreadPool(){ ExecutorService executorService = Executors.newSingleThreadExecutor(); Thread t1 = new MyThread("第一個(gè)"); Thread t2 = new MyThread("第二個(gè)"); Thread t3 = new MyThread("第三個(gè)"); Thread t4 = new MyThread("第四個(gè)"); Thread t5 = new MyThread("第五個(gè)"); executorService.submit(t1); executorService.submit(t2); executorService.submit(t3); executorService.submit(t4); executorService.submit(t5); executorService.shutdown(); }你會(huì)發(fā)現(xiàn)運(yùn)行結(jié)果并沒有什么改變。那么它們的區(qū)別是什么呢?
a,方法參數(shù)
b,返回值不一樣,submit有返回值,execute沒有返回值
c,submit方便Exception的處理
execute是聲明在Executor中的方法。
void execute(Runnable command);submit是聲明在ExecutorService中的方法,有三個(gè)重載。<T> Future<T> submit(Callable<T> task);<T> Future<T> submit(Runnable task, T result);Future<?> submit(Runnable task);submit傳遞Callable的例子: private void createThreadPool(){ ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<String> future = executorService.submit(new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(1000*10); return "執(zhí)行完了"; } }); try { System.out.println(future.get()); }catch (Exception e){ } executorService.shutdown(); }輸出:執(zhí)行完了submit處理異常: private void createThreadPool(){ ExecutorService executorService = Executors.newFixedThreadPool(6); List<Future<String>> futureList = new ArrayList<>(); Future<String> future0 = executorService.submit(new MyCallBack(0)); Future<String> future1 = executorService.submit(new MyCallBack(1)); Future<String> future2 = executorService.submit(new MyCallBack(2)); Future<String> future3 = executorService.submit(new MyCallBack(3)); Future<String> future4 = executorService.submit(new MyCallBack(4)); Future<String> future5 = executorService.submit(new MyCallBack(5)); futureList.add(future0); futureList.add(future1); futureList.add(future2); futureList.add(future3); futureList.add(future4); futureList.add(future5); executorService.shutdown(); for (Future<String> fs : futureList) { try { System.out.println(fs.get()); }catch (Exception e){ System.out.println(e.getMessage()); } } } class MyCallBack implements Callable<String>{ int num; public MyCallBack(int num){ this.num = num; } @Override public String call() throws Exception { return String.valueOf(new Random().nextInt()/num); } }輸出:java.lang.ArithmeticException: / by zero593066746577670865121567560-4067902383432648032,shutdown,shutdownNowa,返回值不同,shutdown沒有返回值,shutdownNow有返回值b,使用效果不一樣,shutdown平穩(wěn)的關(guān)閉線程池,shutdownNow立即關(guān)閉線程池,并返回沒有執(zhí)行的任務(wù)。
3,isShutdown
判斷線程池是否關(guān)閉
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注