java 線程池keepAliveTime的含義說明
之前對線程池中屬性:keepAliveTime比較模糊,而且看過之后過一段時間就會忘掉,于是就在此記錄一下。
keepAliveTime的jdk中的解釋為:
當(dāng)線程數(shù)大于核心時,此為終止前多余的空閑線程等待新任務(wù)的最長時間。
說的讓人感覺比較模糊,總結(jié)一下大概意思為:比如說線程池中最大的線程數(shù)為50,而其中只有40個線程任務(wù)在跑,相當(dāng)于有10個空閑線程,這10個空閑線程不能讓他一直在開著,因為線程的存在也會特別好資源的,所有就需要設(shè)置一個這個空閑線程的存活時間,這么解釋應(yīng)該就很清楚了。
這樣以后忘記了就過來看看就OK了。
補充:線程池的狀態(tài)及KeepAliveTime參數(shù)
五個狀態(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;
循環(huán)getTask方法
/** * Performs blocking or timed wait for a task, depending on * current configuration settings, or returns null if this worker * must exit because of any of: * 1. There are more than maximumPoolSize workers (due to * a call to setMaximumPoolSize). * 2. The pool is stopped. * 3. The pool is shutdown and the queue is empty. * 4. This worker timed out waiting for a task, and timed-out * workers are subject to termination (that is, * {@code allowCoreThreadTimeOut || workerCount > corePoolSize}) * both before and after the timed wait. * * @return task, or null if the worker must exit, in which case * workerCount is decremented */ private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue empty only if necessary. if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } boolean timed; // Are workers subject to culling? for (;;) { int wc = workerCountOf(c); timed = allowCoreThreadTimeOut || wc > corePoolSize; //默認(rèn)allowCoreThreadTimeOut為false,除非程序指定 //(1)當(dāng)沒有超過核心線程時,默認(rèn)allowCoreThreadTimeOut為false時 //timed值為false,始終break掉,不會銷毀線程 //(2)當(dāng)超過核心線程數(shù),默認(rèn)allowCoreThreadTimeOut為false時 //timed值為true,如果超過最大值,則銷毀;如果timeout過,則銷毀 // 如果allowCoreThreadTimeOut為true,則timed始終為true if (wc <= maximumPoolSize && ! (timedOut && timed)) break; if (compareAndDecrementWorkerCount(c)) return null; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) continue retry; // else CAS failed due to workerCount change; retry inner loop } try { Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); if (r != null) return r; timedOut = true; } catch (InterruptedException retry) { timedOut = false; } } }
線程池狀態(tài)大于SHUTDOWN值的兩種情況
1、調(diào)用shutdown方法
當(dāng)線程池調(diào)用了shutdown方法,線程池的狀態(tài)會首先被設(shè)置為SHUTDOWN,然后遍歷線程池中所有線程,調(diào)用一次interrupt方法,如果在休眠中的線程將會激活,激活后的線程以及調(diào)用shutdown方法本身的線程都會嘗試去調(diào)用tryTerminate方法,該方法將判定如果線程池中所有記錄的線程數(shù)為0,則將線程狀態(tài)改為TERMINATED,這個值為3,將大于SHUTDOWN狀態(tài)值。
2、調(diào)用shutdownNow方法
當(dāng)線程調(diào)用了shutdownNow方法后,首先將線程的狀態(tài)修改為STOP,這個狀態(tài)是大于SHUTDOWN值的,接下來它也會通過中斷激活線程,只是它來的更暴力一些,連加鎖和一些基本判斷都沒有,直接中斷;在調(diào)用tryTerminate之前會先清空阻塞隊列中所有的元素,這些元素被組裝為一個List列表作為shutdownNow方法的返回值。換句話說,沒有執(zhí)行的任務(wù)在shutdownNow執(zhí)行后的返回值中可以得到。在程序某些必要的情況下,可以通過線程池的isTerminating,isTerminated,isStopped,isShutdown來對線程做一些狀態(tài)判定。
KeepAliveTime參數(shù)
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)
當(dāng)阻塞隊列中沒有任務(wù)時,等待時間達(dá)到keepAliveTime毫秒值時就會被自動喚醒,而不會永遠(yuǎn)地沉睡下去。
keepAliveTime,如果是通過newCachedThreadPool的話,默認(rèn)是1分鐘超時,如果遇到前面所提到的瞬間沖擊,那么線程池數(shù)量將瞬間快速膨脹,而且這些瞬間膨脹的線程的生命周期最少在1分鐘以上。
如果設(shè)置了該參數(shù),那么當(dāng)timeout的時候,就return null,就會跳出循環(huán),回收線程。
if (wc <= maximumPoolSize && ! (timedOut && timed)) break; if (compareAndDecrementWorkerCount(c)) return null;
allowCoreThreadTimeout : 默認(rèn)情況下核心線程不會退出,可通過將該參數(shù)設(shè)置為true,讓核心線程也退出。
默認(rèn)的Executors工廠,只有newCachedThreadPool,timeout為60秒,出現(xiàn)timeout情況下,而且線程數(shù)超過了核心線程數(shù),會銷毀銷毀線程。保持在corePoolSize數(shù)(如果是cached的,corePoolSize為0)。
/** * Timeout in nanoseconds for idle threads waiting for work. * Threads use this timeout when there are more than corePoolSize * present or if allowCoreThreadTimeOut. Otherwise they wait * forever for new work. */ private volatile long keepAliveTime; /** * If false (default), core threads stay alive even when idle. * If true, core threads use keepAliveTime to time out waiting * for work. */ private volatile boolean allowCoreThreadTimeOut;
線程池最小是corePoolSize,最大是maximumPoolSize,除非設(shè)置了allowCoreThreadTimeOut和超時時間,這種情況線程數(shù)可能減少到0,最大可能是Integer.MAX_VALUE。
Core pool size is the minimum number of workers to keep alive(and not allow to time out etc) unless allowCoreThreadTimeOut is set, in which case the minimum is zero.
/** * Creates a thread pool that creates new threads as needed, but * will reuse previously constructed threads when they are * available. These pools will typically improve the performance * of programs that execute many short-lived asynchronous tasks. * Calls to <tt>execute</tt> will reuse previously constructed * threads if available. If no existing thread is available, a new * thread will be created and added to the pool. Threads that have * not been used for sixty seconds are terminated and removed from * the cache. Thus, a pool that remains idle for long enough will * not consume any resources. Note that pools with similar * properties but different details (for example, timeout parameters) * may be created using {@link ThreadPoolExecutor} constructors. * * @return the newly created thread pool */ public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } /** * Creates a thread pool that creates new threads as needed, but * will reuse previously constructed threads when they are * available, and uses the provided * ThreadFactory to create new threads when needed. * @param threadFactory the factory to use when creating new threads * @return the newly created thread pool * @throws NullPointerException if threadFactory is null */ public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); }
超時timeout設(shè)置為0的話,表示不等待
public E poll(long timeout, TimeUnit unit) throws InterruptedException { return pollFirst(timeout, unit); }
具體如下
public E pollFirst(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { E x; while ( (x = unlinkFirst()) == null) { if (nanos <= 0) return null; nanos = notEmpty.awaitNanos(nanos); } return x; } finally { lock.unlock(); } }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
- Java多線程導(dǎo)致CPU占用100%解決及線程池正確關(guān)閉方式
- 詳解什么是Java線程池的拒絕策略?
- 淺談Java線程池的7大核心參數(shù)
- Java簡單實現(xiàn)線程池
- Java 使用線程池執(zhí)行多個任務(wù)的示例
- 深入理解Java線程池從設(shè)計思想到源碼解讀
- Java 自定義線程池和線程總數(shù)控制操作
- 教你如何監(jiān)控 Java 線程池運行狀態(tài)的操作(必看)
- java多線程CountDownLatch與線程池ThreadPoolExecutor/ExecutorService案例
- Java并發(fā)線程之線程池的知識總結(jié)
- 詳解Java線程池的使用及工作原理
相關(guān)文章
spring?boot?使用Mybatis-plus查詢方法解析
這篇文章主要介紹了spring?boot?使用Mybatis-plus查詢方法解析,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-09-09Java BigDecimal解決double精度丟失的問題
我們在日常開發(fā)中, 有很多時候會遇到小數(shù)(double類型)精確計算,本文主要介紹了Java BigDecimal解決double精度丟失的問題,具有一定的參考價值,感興趣的可以了解一下2023-11-11spring boot結(jié)合Redis實現(xiàn)工具類的方法示例
這篇文章主要介紹了spring boot結(jié)合Redis實現(xiàn)工具類的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11jxl操作excel寫入數(shù)據(jù)不覆蓋原有數(shù)據(jù)示例
網(wǎng)上很多例子,都是用Jxl讀或者寫excel,本文實現(xiàn)的功能就是將數(shù)據(jù)源in.xls的第幾行第幾列數(shù)據(jù)寫入到out.xls的第幾行第幾列,不覆蓋out.xls其他原有的數(shù)據(jù)。2014-03-03深入理解JVM之Java對象的創(chuàng)建、內(nèi)存布局、訪問定位詳解
這篇文章主要介紹了深入理解JVM之Java對象的創(chuàng)建、內(nèi)存布局、訪問定位,結(jié)合實例形式詳細(xì)分析了Java對象的創(chuàng)建、內(nèi)存布局、訪問定位相關(guān)概念、原理、操作技巧與注意事項,需要的朋友可以參考下2019-09-09