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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

线程池状态和使用注意点

發(fā)布時間:2024/4/13 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程池状态和使用注意点 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

線程池的狀態(tài)

  • RUNNING:接收新的任務(wù),執(zhí)行阻塞隊列中的任務(wù)
  • SHUTDOWN:不接受新任務(wù),但是仍然可以處理阻塞隊列中的任務(wù)
  • STOP:不接受新任務(wù),不處理阻塞隊列中的任務(wù),中斷正在處理的任務(wù)
  • TIDYING:所有任務(wù)已終止,workerCount(工作線程數(shù)等于0),進(jìn)入TIDYING狀態(tài)將會執(zhí)行terminated()方法
  • TERMINATED:terminated()方法執(zhí)行完成后進(jìn)入TERMINATED狀態(tài)

線程池狀態(tài)轉(zhuǎn)換如下:

  • RUNNING:能接受新提交的任務(wù),并且也能處理阻塞隊列中的任務(wù);

  • SHUTDOWN:關(guān)閉狀態(tài),不再接受新提交的任務(wù),但卻可以繼續(xù)處理阻塞隊列中已保存的任務(wù)。

  • STOP:不能接受新任務(wù),也不處理隊列中的任務(wù),會中斷正在處理任務(wù)的線程。在線程池處于 RUNNING 或 SHUTDOWN 狀態(tài)時,調(diào)用shutdownNow() 方法會使線程池進(jìn)入到該狀態(tài);

  • TIDYING:如果所有的任務(wù)都已終止了,workerCount (有效線程數(shù)) 為0,線程池進(jìn)入該狀態(tài)后會調(diào)用 terminated() 方法進(jìn)入TERMINATED 狀態(tài)。

  • TERMINATED:在terminated()方法執(zhí)行完后進(jìn)入該狀態(tài)。?

各運(yùn)行狀態(tài)的表示方式:

// runState is stored in the high-order bits private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS; private static final int TIDYING = 2 << COUNT_BITS; private static final int TERMINATED = 3 << COUNT_BITS; //原子變量 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));public void execute(Runnable command) {//判斷提交的Runnable 任務(wù),如果為null,則報NullPointerExceptionif (command == null)throw new NullPointerException(); int c = ctl.get();//判斷當(dāng)前線程數(shù)是否小于核心線程數(shù),如果小于,那就調(diào)用addWorker方法新增一個Worker,也可以理解成一個線程if (workerCountOf(c) < corePoolSize) {//addWorker這個方法主要要做的事就是執(zhí)行command,同時第二個參數(shù)決定以哪個界限來進(jìn)行是否新增線程的判斷,傳入true則代表以核心線程數(shù)為判斷條件if (addWorker(command, true))return;c = ctl.get();}//走到這步邏輯,則說明線程數(shù)大于等于核心線程數(shù),或者addWorker方法調(diào)用失敗了,這時就判斷線程池是否是Running狀態(tài),如果是就調(diào)用offer方法提交線程任務(wù)到任務(wù)隊列中if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();//如果線程池狀態(tài)不是Running,說明線程池已經(jīng)被關(guān)閉,這時就移除新提交到隊列中的任務(wù)if (! isRunning(recheck) && remove(command))//執(zhí)行拒絕策略reject(command);//檢查下當(dāng)前線程數(shù)是不是為0,為0的話就沒有線程執(zhí)行任務(wù)了 else if (workerCountOf(recheck) == 0)//所以就通過addWorker新建一個線程addWorker(null, false);}//走到這步邏輯,要么是線程池狀態(tài)不是Running,說明已經(jīng)關(guān)閉了,要么就是添加任務(wù)進(jìn)任務(wù)隊列時失敗了,說明任務(wù)隊列滿了,這時候就該添加最大線程數(shù)了,傳入false則代表以最大線程數(shù)為判斷條件else if (!addWorker(command, false))//以上addWorker方法如果返回結(jié)果是false,就會執(zhí)行拒絕策略了reject(command);}

內(nèi)置的四種線程池

  • SingleThreadExecutor:單線程化的Executor
  • FiexedThreadPool:固定數(shù)目線程的線程池(隊列數(shù)沒有限制)
  • CachedThreadPool:可緩存的線程池(線程數(shù)沒有限制)
  • ScheduledThreadPool:支持定時及周期性的任務(wù)執(zhí)行的線程池,多數(shù)情況下可用來替代Timer類

這4個線程池都可能存在問題,不建議直接使用,建議使用自定義參數(shù)的線程池

線程池中重要的配置

  • corePoolSize?: 核心線程數(shù)量
  • workQueue?: 等待隊列
  • maximumPoolSize?: 最大線程數(shù)量

提交任務(wù)時,判斷的順序為?corePoolSize --> workQueue -->maximumPoolSize

當(dāng)線程數(shù)小于核心線程數(shù)時,創(chuàng)建核心線程

當(dāng)線程大于等于核心線程數(shù),且任務(wù)隊列未滿時,將任務(wù)放入隊列

當(dāng)線程數(shù)大于核心線程數(shù),且任務(wù)隊列已滿時,檢查最大線程數(shù)是否已滿,若未滿,創(chuàng)建非核心線程,若滿,根據(jù)拒絕策略拋出異常拒絕任務(wù)。

?

拒絕策略—RejectedExecutionHandler

  • AbortPolicy?: 直接拋出異常,這是默認(rèn)策略
  • CallerRunsPolicy?: 用調(diào)用者所在線程來執(zhí)行任務(wù)
  • DiscardOldestPolicy?: 丟棄阻塞隊列中最靠前的任務(wù),并執(zhí)行當(dāng)前任務(wù)
  • DiscardPolicy?: 直接丟棄任務(wù)

?

遇到的坑!!!

  • 任務(wù)提交后長時間沒有執(zhí)行

   1.任務(wù)進(jìn)入了隊列,線程還在執(zhí)行之前的任務(wù)。提交的任務(wù)還在排隊等待執(zhí)行中

  • 線程執(zhí)行任務(wù)中無故消失

? ? ? ? ? 1.? 線程拒絕策略配置為CallerRunsPolicy、DiscardOldestPolicy、DiscardPolicy時 ,線程池滿了不會拋出異常。建議將拒絕策略配置為AbortPolicy

? ? ? ? ? 2.? 一般情況下,代碼只會去捕捉Exception,如果拋出Error(比如內(nèi)存溢出)則會導(dǎo)致線程退出,而異常信息又沒有拿到。最佳的解決辦法是給線程池設(shè)置UncaughtExceptionHandler

?

總結(jié)

以上是生活随笔為你收集整理的线程池状态和使用注意点的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。