Java多線程編程基石ThreadPoolExecutor示例詳解
前言
多線程編程是現(xiàn)代軟件開(kāi)發(fā)中不可或缺的一部分,但是手動(dòng)管理線程可能會(huì)變得非常復(fù)雜,因?yàn)樾枰紤]許多并發(fā)問(wèn)題,例如線程安全和資源競(jìng)爭(zhēng)。為了避免這些問(wèn)題,Java提供了ThreadPoolExecutor類(lèi),它是一種高度優(yōu)化的多線程執(zhí)行器,可以管理線程池、執(zhí)行線程任務(wù)和控制線程池的大小和生命周期等
為什么用線程池
- 線程創(chuàng)建和銷(xiāo)毀的開(kāi)銷(xiāo)較大,每個(gè)線程都需要占用一定的內(nèi)存和系統(tǒng)資源。如果頻繁地創(chuàng)建和銷(xiāo)毀線程,會(huì)導(dǎo)致系統(tǒng)的性能下降。
- 手動(dòng)管理線程容易出現(xiàn)線程安全和資源競(jìng)爭(zhēng)的問(wèn)題,例如,多個(gè)線程同時(shí)訪問(wèn)共享變量可能導(dǎo)致數(shù)據(jù)不一致或者死鎖等問(wèn)題。
- 如果并發(fā)訪問(wèn)的線程數(shù)量很大,可能會(huì)導(dǎo)致系統(tǒng)資源不足,例如,內(nèi)存不足或者CPU過(guò)度使用等問(wèn)題。
參數(shù)介紹
- corePoolSize:核心線程池大小,即線程池中始終存在的線程數(shù)量,除非設(shè)置了allowCoreThreadTimeOut參數(shù),默認(rèn)情況下,即使空閑,核心線程也不會(huì)被回收。
- maximumPoolSize:線程池的最大線程數(shù),即可以同時(shí)執(zhí)行的最大線程數(shù)量。
- keepAliveTime:非核心線程的空閑存活時(shí)間,當(dāng)非核心線程空閑時(shí)間超過(guò)這個(gè)時(shí)間,就會(huì)被回收。
- unit:keepAliveTime的時(shí)間單位。
- workQueue:任務(wù)隊(duì)列,用于存儲(chǔ)等待執(zhí)行的任務(wù),有多種實(shí)現(xiàn)方式,例如ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue等。
- threadFactory:用于創(chuàng)建新線程的工廠類(lèi),可以自定義線程名稱(chēng)、線程優(yōu)先級(jí)等屬性。
- handler:線程池的拒絕策略,當(dāng)線程池已經(jīng)達(dá)到最大線程數(shù),并且任務(wù)隊(duì)列已經(jīng)滿(mǎn)了,新的任務(wù)將被拒絕執(zhí)行,可以設(shè)置拒絕策略來(lái)處理這種情況。
核心線程數(shù)和最大線程數(shù)設(shè)置
- CPU密集型任務(wù):CPU密集型任務(wù)的特點(diǎn)是線程在執(zhí)行任務(wù)時(shí)會(huì)一直利用CPU,對(duì)于這種情況要盡可能的避免發(fā)生線程上下文的切換。一般來(lái)說(shuō)對(duì)于CPU密集型任務(wù)設(shè)置線程數(shù)為CPU核心數(shù)+1。
- IO密集型任務(wù):線程在執(zhí)行IO密集型任務(wù)時(shí),可能大部分時(shí)間都浪費(fèi)在阻塞IO上了,所以對(duì)于IO密集型任務(wù)來(lái)說(shuō)我們通常會(huì)設(shè)置線程數(shù)為CPU核心數(shù)*2。不過(guò)這樣子也不一定是最佳的,我們可以通過(guò)公式來(lái)進(jìn)行計(jì)算:線程數(shù) = CPU 核心數(shù) *(1+平均等待時(shí)間/平均工作時(shí)間),盡可能的還要根據(jù)壓縮來(lái)進(jìn)行調(diào)整。
使用示例
public class CustomThreadPoolDemo { public static void main(String[] args) { // 創(chuàng)建線程池,大小為3,最大線程數(shù)為6,空閑線程存活時(shí)間為5秒,使用自定義線程工廠和拒絕策略 ThreadPoolExecutor executor = new ThreadPoolExecutor(3, 6, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10), new CustomThreadFactory(), new CustomRejectedExecutionHandler()); // 提交10個(gè)任務(wù) for (int i = 0; i < 10; i++) { executor.submit(new Task(i)); } // 關(guān)閉線程池 executor.shutdown(); } static class Task implements Runnable { private int taskId; public Task(int taskId) { this.taskId = taskId; } @Override public void run() { System.out.println("Task " + taskId + " is running in thread " + Thread.currentThread().getName()); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Task " + taskId + " is done."); } } static class CustomThreadFactory implements java.util.concurrent.ThreadFactory { private int count = 1; @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setName("CustomThreadPool-" + count++); return t; } } static class CustomRejectedExecutionHandler implements java.util.concurrent.RejectedExecutionHandler { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { System.out.println("Task " + ((Task) r).taskId + " is rejected."); } } }
該示例代碼使用ThreadPoolExecutor
類(lèi)創(chuàng)建了一個(gè)大小為3,最大線程數(shù)為6,空閑線程存活時(shí)間為5秒的線程池,任務(wù)隊(duì)列的大小為10,使用了自定義的線程工廠和拒絕策略。然后提交了10個(gè)任務(wù),每個(gè)任務(wù)輸出了當(dāng)前線程的名稱(chēng),并休眠了3秒鐘。當(dāng)程序執(zhí)行時(shí),可能會(huì)出現(xiàn)任務(wù)被拒絕執(zhí)行的情況,拒絕策略會(huì)輸出任務(wù)被拒絕的信息。
線程池執(zhí)行任務(wù)的流程
ThreadPoolExecutor提供了兩種執(zhí)行任務(wù)的方法:
Future<?> submit(Runnable task) void execute(Runnable command)
實(shí)際上submit中也是調(diào)用了execute方法
public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; }
線程池執(zhí)行流程圖
源碼解讀
基礎(chǔ)屬性和變量
private final AtomicInteger ctl
線程池源碼中使用ctl通過(guò)高低位的方式來(lái)記錄線程池的狀態(tài)和當(dāng)前線程池中的工作線程數(shù)量。
Integer占用4個(gè)字節(jié)也就是32位,線程池有5種狀態(tài),要標(biāo)識(shí)5種狀態(tài)需要3位
前三位
private static final int COUNT_BITS = Integer.SIZE - 3; private static final int CAPACITY = (1 << COUNT_BITS) - 1; // 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;
Integer.SIZE為32,所以COUNT_BITS為29,最終各個(gè)狀態(tài)對(duì)應(yīng)的二級(jí)制為:
RUNNING:11100000 00000000 00000000 00000000
SHUTDOWN:00000000 00000000 00000000 00000000
STOP:00100000 00000000 00000000 00000000
TIDYING:01000000 00000000 00000000 00000000
TERMINATED:01100000 00000000 00000000 00000000
execute(Runnable command)
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); //ctl初始值是ctlOf(RUNNING, 0),表示線程池處于運(yùn)行中,工作線程數(shù)為0 int c = ctl.get(); //判斷工作線程是否小于核心線程數(shù) if (workerCountOf(c) < corePoolSize) { //小于核心線程要新增工作線程 if (addWorker(command, true)) return; //新增失敗重新獲取一次ctl c = ctl.get(); } //線程池是否處于Running狀態(tài) && 入隊(duì)是否成功 if (isRunning(c) && workQueue.offer(command)) {//入隊(duì)成功 //重新獲取ctl int recheck = ctl.get(); //如果線程池不是Running狀態(tài)就需要移除掉這個(gè)任務(wù) if (! isRunning(recheck) && remove(command)) //觸發(fā)拒絕策略 reject(command); //工作線程為0時(shí)要去創(chuàng)建新的工作線程 else if (workerCountOf(recheck) == 0) addWorker(null, false); } // 如果線程池狀態(tài)不是RUNNING,或者線程池狀態(tài)是RUNNING但是隊(duì)列滿(mǎn)了,則去添加一個(gè)非核心工作線程。false表示非核心線程 else if (!addWorker(command, false)) reject(command); }
addWorker(Runnable firstTask, boolean core)
//core:true核心線程 false非核心線程 private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { //獲取ctl值 int c = ctl.get(); //獲取高3位 int rs = runStateOf(c); // 線程池如果是SHUTDOWN狀態(tài)并且隊(duì)列非空則創(chuàng)建線程,如果隊(duì)列為空則不創(chuàng)建線程 // 線程池如果是STOP狀態(tài)則直接不創(chuàng)建線程 if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { //獲取工作線程數(shù) int wc = workerCountOf(c); //工作線程數(shù)超過(guò)規(guī)定數(shù)量則不創(chuàng)建線程 if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; //修改工作線程 if (compareAndIncrementWorkerCount(c)) //成功則退出 retry這個(gè)循環(huán) break retry; //CAS失敗說(shuō)明有其他線程也在增加工作線程數(shù)量,此時(shí)重新獲取ctl值 c = ctl.get(); // Re-read ctl //如果發(fā)現(xiàn)線程池的狀態(tài)發(fā)生了變化,則繼續(xù)回到retry,重新判斷線程池的狀態(tài)是不是SHUTDOWN或STOP // 如果狀態(tài)沒(méi)有變化,則繼續(xù)利用cas來(lái)增加工作線程數(shù),直到cas成功 if (runStateOf(c) != rs) continue retry; // else CAS failed due to workerCount change; retry inner loop } } //到了這里說(shuō)明ctl新增成功 boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { //Worker實(shí)現(xiàn)了Runnable接口 在構(gòu)造一個(gè)Worker對(duì)象時(shí),就會(huì)利用ThreadFactory新建一個(gè)線程 w = new Worker(firstTask); //拿出線程對(duì)象此時(shí)線程還沒(méi)有start啟動(dòng) final Thread t = w.thread; if (t != null) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // 獲取高三位 int rs = runStateOf(ctl.get()); // 如果線程池的狀態(tài)是RUNNING // 或者線程池的狀態(tài)變成了SHUTDOWN,但是當(dāng)前線程沒(méi)有自己的第一個(gè)任務(wù),那就表示當(dāng)前調(diào)用addWorker方法是為了從隊(duì)列中獲取任務(wù)來(lái)執(zhí)行 // 正常情況下線程池的狀態(tài)如果是SHUTDOWN,是不能創(chuàng)建新的工作線程的,但是隊(duì)列中如果有任務(wù),那就是上面說(shuō)的特例情況 if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { // 如果Worker對(duì)象對(duì)應(yīng)的線程已經(jīng)在運(yùn)行了,那就有問(wèn)題,直接拋異常 if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); // workers用來(lái)記錄當(dāng)前線程池中工作線程,調(diào)用線程池的shutdown方法時(shí)會(huì)遍歷worker對(duì)象中斷對(duì)應(yīng)線程 workers.add(w); int s = workers.size(); // largestPoolSize用來(lái)跟蹤線程池在運(yùn)行過(guò)程中工作線程數(shù)的峰值 if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } //啟動(dòng)線程 if (workerAdded) { t.start(); workerStarted = true; } } } finally { // 在上述過(guò)程中如果拋了異常,需要從works中移除所添加的work,并且還要修改ctl,工作線程數(shù)-1,表示新建工作線程失敗 if (! workerStarted) addWorkerFailed(w); } return workerStarted; }
addWorker核心邏輯:
- 先判斷工作線程數(shù)是否超過(guò)了限制
- 修改ctl,使得工作線程數(shù)+1
- 構(gòu)造Work對(duì)象,并把它添加到workers集合中
- 啟動(dòng)Work對(duì)象對(duì)應(yīng)的工作線程
runWorker(this)
剛剛有說(shuō)到Worker實(shí)現(xiàn)了Runnable接口,看看他重寫(xiě)的Run方法中執(zhí)行過(guò)什么
Worker(Runnable firstTask) { setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } /** Delegates main run loop to outer runWorker */ public void run() { runWorker(this); }
final void runWorker(Worker w) { //獲取當(dāng)前工作線程 Thread wt = Thread.currentThread(); //獲取第一個(gè)任務(wù) Runnable task = w.firstTask; //置空 w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { //判斷當(dāng)前第一個(gè)任務(wù)是否為空,為空的話(huà)從阻塞隊(duì)列獲取一個(gè)任務(wù),阻塞隊(duì)列也為空就會(huì)阻塞在getTask()方法中 //也不會(huì)一直阻塞下去,keepAliveTime超時(shí)后還沒(méi)有獲取到任務(wù)就會(huì)返回null,退出循環(huán),這個(gè)線程也就是中止了 while (task != null || (task = getTask()) != null) { w.lock(); //線程池狀態(tài)為STOP,則要中斷自己,但是如果發(fā)現(xiàn)中斷標(biāo)記為true,那是不對(duì)的,因?yàn)榫€程池狀態(tài)不是STOP,工作線程仍然是要正常工作的,不能中斷掉,算是SHUTDOWN,也要等任務(wù)都執(zhí)行完之后,線程才結(jié)束,而目前線程還在執(zhí)行任務(wù)的過(guò)程中,不能中斷 if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { //空方法給自定義線程池實(shí)現(xiàn) beforeExecute(wt, task); Throwable thrown = null; try { //執(zhí)行任務(wù) task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { //空方法給自定義線程池實(shí)現(xiàn) afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } //正常退出了while循環(huán) // completedAbruptly=false,表示線程正常退出 completedAbruptly = false; } finally { //如果線程正常退出這個(gè)線程會(huì)自然死亡 //但是如果是由于執(zhí)行任務(wù)的時(shí)候拋了異常,那么這個(gè)線程不應(yīng)該直接結(jié)束,而應(yīng)該繼續(xù)從隊(duì)列中獲取下一個(gè)任務(wù) processWorkerExit(w, completedAbruptly); } }
processWorkerExit(Worker w, boolean completedAbruptly)
private void processWorkerExit(Worker w, boolean completedAbruptly) { //如果completedAbruptly為true,表示是執(zhí)行任務(wù)的時(shí)候拋了異常,那就修改ctl,工作線程數(shù)-1 if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; // 將當(dāng)前Work對(duì)象從workers中移除 workers.remove(w); } finally { mainLock.unlock(); } // 因?yàn)楫?dāng)前是處理線程退出流程中,所以要嘗試去修改線程池的狀態(tài)為T(mén)INDYING tryTerminate(); //獲取當(dāng)前ctl值 int c = ctl.get(); // 如果線程池的狀態(tài)為RUNNING或者SHUTDOWN,則可能要替補(bǔ)一個(gè)線程 if (runStateLessThan(c, STOP)) { // completedAbruptly為false,表示線程是正常要退出了,則看是否需要保留線程 if (!completedAbruptly) { // 如果allowCoreThreadTimeOut為true,但是阻塞隊(duì)列中還有任務(wù),那就至少得保留一個(gè)工作線程來(lái)處理阻塞隊(duì)列中的任務(wù) // 如果allowCoreThreadTimeOut為false,那min就是corePoolSize,表示至少得保留corePoolSize個(gè)工作線程活著 int min = allowCoreThreadTimeOut ? 0 : corePoolSize; if (min == 0 && ! workQueue.isEmpty()) min = 1; // 如果當(dāng)前工作線程數(shù)大于等于min,則表示符合所需要保留的最小線程數(shù),那就直接return,不會(huì)調(diào)用下面的addWorker方法新開(kāi)一個(gè)工作線程了 if (workerCountOf(c) >= min) return; // replacement not needed } //新開(kāi)工作線程 addWorker(null, false); } }
某個(gè)工作線程正常情況下會(huì)不停的循環(huán)從阻塞隊(duì)列中獲取任務(wù)來(lái)執(zhí)行,正常情況下就是通過(guò)阻塞來(lái)保證線程永遠(yuǎn)活著,但是會(huì)有一些特殊情況:
- 如果線程被中斷了,那就會(huì)退出循環(huán),然后做一些善后處理,比如ctl中的工作線程數(shù)-1,然后自己運(yùn)行結(jié)束
- 如果線程阻塞超時(shí)了,那也會(huì)退出循環(huán),此時(shí)就需要判斷線程池中的當(dāng)前工作線程夠不夠,比如是否有corePoolSize個(gè)工作線程,如果不夠就需要新開(kāi)一個(gè)線程,然后當(dāng)前線程自己運(yùn)行結(jié)束,這種看上去效率比較低,但是也沒(méi)辦法,當(dāng)然如果當(dāng)前工作線程數(shù)足夠,那就正常,自己正常的運(yùn)行結(jié)束即可
- 如果線程是在執(zhí)行任務(wù)的時(shí)候拋了移除,從而退出循環(huán),那就直接新開(kāi)一個(gè)線程作為替補(bǔ),當(dāng)然前提是線程池的狀態(tài)是RUNNING
getTask()
private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? for (;;) { int c = ctl.get(); int rs = runStateOf(c); // 如果線程池狀態(tài)是STOP,表示當(dāng)前線程不需要處理任務(wù)了,那就修改ctl工作線程數(shù)-1 // 如果線程池狀態(tài)是SHUTDOWN,但是阻塞隊(duì)列中為空,表示當(dāng)前任務(wù)沒(méi)有任務(wù)要處理了,那就修改ctl工作線程數(shù)-1 // return null表示當(dāng)前線程無(wú)需處理任務(wù),線程退出 if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } //當(dāng)前工作線程數(shù) int wc = workerCountOf(c); // 用來(lái)判斷當(dāng)前線程是無(wú)限阻塞還是超時(shí)阻塞,如果一個(gè)線程超時(shí)阻塞,那么一旦超時(shí)了,那么這個(gè)線程最終就會(huì)退出 // 如果是無(wú)限阻塞,那除非被中斷了,不然這個(gè)線程就一直等著獲取隊(duì)列中的任務(wù) // allowCoreThreadTimeOut為true,表示線程池中的所有線程都可以被回收掉,則當(dāng)前線程應(yīng)該直接使用超時(shí)阻塞,一旦超時(shí)就回收 // allowCoreThreadTimeOut為false,則要看當(dāng)前工作線程數(shù)是否超過(guò)了corePoolSize,如果超過(guò)了,則表示超過(guò)部分的線程要用超時(shí)阻塞,一旦超時(shí)就回收 boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; // 如果工作線程數(shù)超過(guò)了工作線程的最大限制或者線程超時(shí)了,則要修改ctl,工作線程數(shù)減1,并且return null // return null就會(huì)導(dǎo)致外層的while循環(huán)退出,從而導(dǎo)致線程直接運(yùn)行結(jié)束 // 直播課程里會(huì)細(xì)講timed && timedOut if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { if (compareAndDecrementWorkerCount(c)) return null; continue; } try { // 要么超時(shí)阻塞,要么無(wú)限阻塞 Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); // 表示沒(méi)有超時(shí),在阻塞期間獲取到了任務(wù) if (r != null) return r; // 超時(shí)了,重新進(jìn)入循環(huán),上面的代碼會(huì)判斷出來(lái)當(dāng)前線程阻塞超時(shí)了,最后return null,線程會(huì)運(yùn)行結(jié)束 timedOut = true; } catch (InterruptedException retry) { // 如果線程池的狀態(tài)變成了STOP或者SHUTDOWN,最終也會(huì)return null,線程會(huì)運(yùn)行結(jié)束 // 但是如果線程池的狀態(tài)仍然是RUNNING,那當(dāng)前線程會(huì)繼續(xù)從隊(duì)列中去獲取任務(wù),表示忽略了本次中斷 // 只有通過(guò)調(diào)用線程池的shutdown方法或shutdownNow方法才能真正中斷線程池中的線程 timedOut = false; } } }
shutdown()
public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // 修改ctl,將線程池狀態(tài)改為SHUTDOWN advanceRunState(SHUTDOWN); // 中斷工作線程 interruptIdleWorkers(); // 空方法,給子類(lèi)擴(kuò)展使用 onShutdown(); // hook for ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } tryTerminate(); }
private void interruptIdleWorkers(boolean onlyOne) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // 遍歷所有正在工作的線程,要么在執(zhí)行任務(wù),要么在阻塞等待任務(wù) for (Worker w : workers) { Thread t = w.thread; // 如果線程沒(méi)有被中斷,并且能夠拿到鎖,就中斷線程 // Worker在執(zhí)行任務(wù)時(shí)會(huì)先加鎖,執(zhí)行完任務(wù)之后會(huì)釋放鎖 // 所以只要這里拿到了鎖,就表示線程空出來(lái)了,可以中斷了 if (!t.isInterrupted() && w.tryLock()) { try { t.interrupt(); } catch (SecurityException ignore) { } finally { w.unlock(); } } if (onlyOne) break; } } finally { mainLock.unlock(); } }
總結(jié)
ThreadPoolExecutor是Java并發(fā)編程中非常重要的一個(gè)類(lèi),它可以?xún)?yōu)化多線程編程的效率和可靠性。在本文中,我們深入探討了ThreadPoolExecutor的實(shí)現(xiàn)原理、工作機(jī)制和使用方法,總結(jié)如下:
首先,ThreadPoolExecutor是一種高度優(yōu)化的多線程執(zhí)行器,它可以管理線程池、執(zhí)行線程任務(wù)和控制線程池的大小和生命周期等。ThreadPoolExecutor的實(shí)現(xiàn)基于生產(chǎn)者-消費(fèi)者模型,它可以根據(jù)任務(wù)隊(duì)列中的任務(wù)數(shù)量自動(dòng)調(diào)整線程池的大小,從而實(shí)現(xiàn)對(duì)系統(tǒng)資源的最優(yōu)利用。
其次,ThreadPoolExecutor的使用非常靈活,可以通過(guò)配置ThreadPoolExecutor的參數(shù)來(lái)實(shí)現(xiàn)不同的線程池策略,例如核心線程數(shù)、最大線程數(shù)、任務(wù)隊(duì)列類(lèi)型、拒絕策略等。此外,ThreadPoolExecutor還提供了一些重要的方法,例如submit()、execute()和shutdown()等,用于提交任務(wù)、執(zhí)行任務(wù)和關(guān)閉線程池。
最后,在高并發(fā)環(huán)境下,應(yīng)盡可能避免使用無(wú)界隊(duì)列,以防止內(nèi)存泄漏和系統(tǒng)資源耗盡。此外,還可以通過(guò)使用線程池監(jiān)視器和線程池飽和策略來(lái)監(jiān)控線程池的狀態(tài)和性能,以確保系統(tǒng)的穩(wěn)定性和可靠性。
以上就是Java多線程編程基石ThreadPoolExecutor示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Java多線程ThreadPoolExecutor的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 注冊(cè)或者點(diǎn)擊按鈕時(shí),怎么防止用戶(hù)重復(fù)提交數(shù)據(jù)(實(shí)例講解)
- Java多線程循環(huán)柵欄CyclicBarrier正確使用方法
- Java多線程正確使用倒計(jì)時(shí)協(xié)調(diào)器CountDownLatch方法詳解
- Java多線程場(chǎng)景解析volatile和AtomicLong區(qū)別原理
- java并發(fā)無(wú)鎖多線程單線程示例詳解
- ReentrantLock從源碼解析Java多線程同步學(xué)習(xí)
- java多線程事務(wù)加鎖引發(fā)bug用戶(hù)重復(fù)注冊(cè)解決分析
相關(guān)文章
Java行為型設(shè)計(jì)模式之外觀設(shè)計(jì)模式詳解
外觀模式為多個(gè)復(fù)雜的子系統(tǒng),提供了一個(gè)一致的界面,使得調(diào)用端只和這個(gè)接口發(fā)生調(diào)用,而無(wú)須關(guān)系這個(gè)子系統(tǒng)內(nèi)部的細(xì)節(jié)。本文將通過(guò)示例詳細(xì)為大家講解一下外觀模式,需要的可以參考一下2022-11-11java并發(fā)等待條件的實(shí)現(xiàn)原理詳解
這篇文章主要介紹了java并發(fā)等待條件的實(shí)現(xiàn)原理詳解,還是比較不錯(cuò)的,這里分享給大家,供需要的朋友參考。2017-11-11Java中的IP地址和InetAddress類(lèi)使用詳解
這篇文章主要介紹了Java中的IP地址和InetAddress類(lèi)使用詳解,是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-10-10Java實(shí)現(xiàn)猜數(shù)字小游戲代碼
大家好,本篇文章主要講的是Java實(shí)現(xiàn)猜數(shù)字小游戲代碼,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下2022-01-01Java 隊(duì)列實(shí)現(xiàn)原理及簡(jiǎn)單實(shí)現(xiàn)代碼
這篇文章主要介紹了Java 隊(duì)列實(shí)現(xiàn)原理及簡(jiǎn)單實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2016-10-10Spring實(shí)戰(zhàn)之Bean定義中的SpEL表達(dá)式語(yǔ)言支持操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之Bean定義中的SpEL表達(dá)式語(yǔ)言支持操作,結(jié)合實(shí)例形式分析了Bean定義中的SpEL表達(dá)式語(yǔ)言操作步驟與實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-12-12Java類(lèi)加載器和類(lèi)加載機(jī)制實(shí)例分析
這篇文章主要介紹了Java類(lèi)加載器和類(lèi)加載機(jī)制,結(jié)合實(shí)例形式分析了java類(lèi)加載器與類(lèi)加載機(jī)制原理、實(shí)現(xiàn)方法及相關(guān)操作技巧,需要的朋友可以參考下2019-07-07