日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

java 线程池ThreadPoolExecutor

發布時間:2025/7/14 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 线程池ThreadPoolExecutor 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線程池

線程池的作用:

線程池作用就是限制系統中執行線程的數量。
根 據系統的環境情況,可以自動或手動設置線程數量,達到運行的最佳效果;少了浪費了系統資源,多了造成系統擁擠效率不高。用線程池控制線程數量,其他線程排 隊等候。一個任務執行完畢,再從隊列的中取最前面的任務開始執行。若隊列中沒有等待進程,線程池的這一資源處于等待。當一個新任務需要運行時,如果線程池 中有等待的工作線程,就可以開始運行了;否則進入等待隊列。

為什么要用線程池:

1.減少了創建和銷毀線程的次數,每個工作線程都可以被重復利用,可執行多個任務。

2.可以根據系統的承受能力,調整線程池中工作線線程的數目,防止因為消耗過多的內存,而把服務器累趴下(每個線程需要大約1MB內存,線程開的越多,消耗的內存也就越大,最后死機)。

Java里面線程池的頂級接口是Executor,但是嚴格意義上講Executor并不是一個線程池,而只是一個執行線程的工具。真正的線程池接口是ExecutorService。

比較重要的幾個類:

ExecutorService: 真正的線程池接口。

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

ThreadPoolExecutor: ExecutorService的默認實現。

ScheduledThreadPoolExecutor: 繼承ThreadPoolExecutor的ScheduledExecutorService接口實現,周期性任務調度的類實現。

要配置一個線程池是比較復雜的,尤其是對于線程池的原理不是很清楚的情況下,很有可能配置的線程池不是較優的,因此在Executors類里面提供了一些靜態工廠,生成一些常用的線程池。

Java線程池的參數

關于Java線程池的參數設置。線程池是Java多線程里開發里的重要內容,使用難度不大,但如何用好就要明白參數的含義和如何去設置。

一、ThreadPoolExecutor的重要參數
? ? 1、corePoolSize:核心線程數
? ? ? ? * 核心線程會一直存活,及時沒有任務需要執行
? ? ? ? * 當線程數小于核心線程數時,即使有線程空閑,線程池也會優先創建新線程處理
? ? ? ? * 設置allowCoreThreadTimeout=true(默認false)時,核心線程會超時關閉

? ? 2、queueCapacity:任務隊列容量(阻塞隊列)
? ? ? ? * 當核心線程數達到最大時,新任務會放在隊列中排隊等待執行

? ? 3、maxPoolSize:最大線程數
? ? ? ? * 當線程數>=corePoolSize,且任務隊列已滿時。線程池會創建新線程來處理任務
? ? ? ? * 當線程數=maxPoolSize,且任務隊列已滿時,線程池會拒絕處理任務而拋出異常

? ? 4、 keepAliveTime:線程空閑時間
? ? ? ? * 當線程空閑時間達到keepAliveTime時,線程會退出,直到線程數量=corePoolSize
? ? ? ? * 如果allowCoreThreadTimeout=true,則會直到線程數量=0

? ? 5、allowCoreThreadTimeout:允許核心線程超時
? ? 6、rejectedExecutionHandler:任務拒絕處理器
? ? ? ? * 兩種情況會拒絕處理任務:
? ? ? ? ? ? - 當線程數已經達到maxPoolSize,切隊列已滿,會拒絕新任務
? ? ? ? ? ? - 當線程池被調用shutdown()后,會等待線程池里的任務執行完畢,再shutdown。如果在調用shutdown()和線程池真正shutdown之間提交任務,會拒絕新任務
? ? ? ? * 線程池會調用rejectedExecutionHandler來處理這個任務。如果沒有設置默認是AbortPolicy,會拋出異常
? ? ? ? * ThreadPoolExecutor類有幾個內部實現類來處理這類情況:
? ? ? ? ? ? - AbortPolicy 丟棄任務,拋運行時異常
? ? ? ? ? ? - CallerRunsPolicy 執行任務
? ? ? ? ? ? - DiscardPolicy 忽視,什么都不會發生
? ? ? ? ? ? - DiscardOldestPolicy 從隊列中踢出最先進入隊列(最后一個執行)的任務
? ? ? ? * 實現RejectedExecutionHandler接口,可自定義處理器

二、ThreadPoolExecutor執行順序
? ? ? ? 線程池按以下行為執行任務
? ? 1. 當線程數小于核心線程數時,創建線程。
? ? 2. 當線程數大于等于核心線程數,且任務隊列未滿時,將任務放入任務隊列。
? ? 3. 當線程數大于等于核心線程數,且任務隊列已滿
? ? ? ? - 若線程數小于最大線程數,創建線程
? ? ? ? - 若線程數等于最大線程數,拋出異常,拒絕任務

三、如何設置參數
? ? 1、默認值
? ? ? ? * corePoolSize=1
? ? ? ? * queueCapacity=Integer.MAX_VALUE
? ? ? ? * maxPoolSize=Integer.MAX_VALUE
? ? ? ? * keepAliveTime=60s
? ? ? ? * allowCoreThreadTimeout=false
? ? ? ? * rejectedExecutionHandler=AbortPolicy()

? ? 2、如何來設置
? ? ? ? * 需要根據幾個值來決定
? ? ? ? ? ? - tasks :每秒的任務數,假設為500~1000
? ? ? ? ? ? - taskcost:每個任務花費時間,假設為0.1s
? ? ? ? ? ? - responsetime:系統允許容忍的最大響應時間,假設為1s
? ? ? ? * 做幾個計算
? ? ? ? ? ? - corePoolSize = 每秒需要多少個線程處理??
? ? ? ? ? ? ? ? * threadcount = tasks/(1/taskcost) =tasks*taskcout =? (500~1000)*0.1 = 50~100 個線程。corePoolSize設置應該大于50
? ? ? ? ? ? ? ? * 根據8020原則,如果80%的每秒任務數小于800,那么corePoolSize設置為80即可
? ? ? ? ? ? - queueCapacity = (coreSizePool/taskcost)*responsetime
? ? ? ? ? ? ? ? * 計算可得 queueCapacity = 80/0.1*1 = 80。意思是隊列里的線程可以等待1s,超過了的需要新開線程來執行
? ? ? ? ? ? ? ? * 切記不能設置為Integer.MAX_VALUE,這樣隊列會很大,線程數只會保持在corePoolSize大小,當任務陡增時,不能新開線程來執行,響應時間會隨之陡增。
? ? ? ? ? ? - maxPoolSize = (max(tasks) - queueCapacity)/(1/taskcost)
? ? ? ? ? ? ? ? * 計算可得 maxPoolSize = (1000-80)/10 = 92
? ? ? ? ? ? ? ? * (最大任務數-隊列容量)/每個線程每秒處理能力 = 最大線程數
? ? ? ? ? ? - rejectedExecutionHandler:根據具體情況來決定,任務不重要可丟棄,任務重要則要利用一些緩沖機制來處理
? ? ? ? ? ? - keepAliveTime和allowCoreThreadTimeout采用默認通常能滿足

? ? 3、 以上都是理想值,實際情況下要根據機器性能來決定。如果在未達到最大線程數的情況機器cpu load已經滿了,則需要通過升級硬件(呵呵)和優化代碼,降低taskcost來處理。

線程池代碼

public class ThreadPoolExecutor extends AbstractExecutorService {.....public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue);public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);... }

 從上面的代碼可以得知,ThreadPoolExecutor繼承了AbstractExecutorService類,并提供了四個構造器,事實上,通過觀察每個構造器的源碼具體實現,發現前面三個構造器都是調用的第四個構造器進行的初始化工作。

?  各個參數的含義:

  • corePoolSize:核心池的大小,這個參數跟后面講述的線程池的實現原理有非常大的關系。在創建了線程池后,默認情況下,線程池中并沒有任何線程,而是等待有任務到來才創建線程去執行任務,除非調用了prestartAllCoreThreads()或者prestartCoreThread()方法,從這2個方法的名字就可以看出,是預創建線程的意思,即在沒有任務到來之前就創建corePoolSize個線程或者一個線程。默認情況下,在創建了線程池后,線程池中的線程數為0,當有任務來之后,就會創建一個線程去執行任務,當線程池中的線程數目達到corePoolSize后,就會把到達的任務放到緩存隊列當中;
  • maximumPoolSize:線程池最大線程數,這個參數也是一個非常重要的參數,它表示在線程池中最多能創建多少個線程;
  • keepAliveTime:表示線程沒有任務執行時最多保持多久時間會終止。默認情況下,只有當線程池中的線程數大于corePoolSize時,keepAliveTime才會起作用,直到線程池中的線程數不大于corePoolSize,即當線程池中的線程數大于corePoolSize時,如果一個線程空閑的時間達到keepAliveTime,則會終止,直到線程池中的線程數不超過corePoolSize。但是如果調用了allowCoreThreadTimeOut(boolean)方法,在線程池中的線程數不大于corePoolSize時,keepAliveTime參數也會起作用,直到線程池中的線程數為0;
  • unit:參數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性:
TimeUnit.DAYS; // TimeUnit.HOURS; //小時 TimeUnit.MINUTES; //分鐘 TimeUnit.SECONDS; // TimeUnit.MILLISECONDS; //毫秒 TimeUnit.MICROSECONDS; //微妙 TimeUnit.NANOSECONDS; //納秒
  • workQueue:一個阻塞隊列,用來存儲等待執行的任務,這個參數的選擇也很重要,會對線程池的運行過程產生重大影響,一般來說,這里的阻塞隊列有以下幾種選擇:
ArrayBlockingQueue; LinkedBlockingQueue; SynchronousQueue;

  ArrayBlockingQueue和PriorityBlockingQueue使用較少,一般使用LinkedBlockingQueue和Synchronous。線程池的排隊策略與BlockingQueue有關。

  • threadFactory:線程工廠,主要用來創建線程;
  • handler:表示當拒絕處理任務時的策略,有以下四種取值:
ThreadPoolExecutor.AbortPolicy:丟棄任務并拋出RejectedExecutionException異常。 ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。 ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程) ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務

  最全參數的線程池:

// 最全參數的線程池
// 參數順序:核心線程數、最大線程數、空閑線程超時時間、超時后線程銷毀、隊列長度、線程構造器、執行任務
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(1),new ThreadFactoryBuilder().setNameFormat("thread-%d").build(), new ThreadPoolExecutor.CallerRunsPolicy());for (int i = 0; i<100; i++) {final int finalI = i;threadPoolExecutor.execute(new Runnable() {@Overridepublic void run() {System.out.println(finalI + ":" + Thread.currentThread().getName() + " is running");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(finalI + ":" + Thread.currentThread().getName() + " is end");}});}threadPoolExecutor.shutdown();

執行方法

execute方法無返回參數,如需接收方法執行返回參數可使用callable方法,并用Future接收返回的參數。

Future<String> future = threadPoolExecutor.callable(...)

?

注意事項:

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

newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
newFixedThreadPool 創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。
newScheduledThreadPool 創建一個定長線程池,支持定時及周期性任務執行。
newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

一般場景也可以采用以上方法,但是建議還是采用自己配置參數的方法,這樣可以使得線程池可控,自己掌握。

轉載于:https://www.cnblogs.com/loveyaoyao/p/10217253.html

總結

以上是生活随笔為你收集整理的java 线程池ThreadPoolExecutor的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。