线程与线程池(一条龙详解)
一:前言
一個問題引出的學習筆記
并發類庫提供的線程池實現有哪些?
其實Executors已經為我們封裝好了 4 種常見的功能線程池,如下:
- 定長線程池(FixedThreadPool)
- 定時線程池(ScheduledThreadPool )
- 可緩存線程池(CachedThreadPool)
- 單線程化線程池(SingleThreadExecutor)
那么接下來就復習一波線程和線程池
二:線程
1:關于線程的理解
- 自我理解:(這是在javaweb中的文件上傳部分 實際用到的線程 來幫助理解線程)
一個線程就是一條執行路徑 ,實際例子當中 我們請求一個頁面如果需要很長的時間的話,這時候我們需要設置線程來執行 請求消息中的代碼,然后再寫一個代碼先顯示出請求等待的信息 - 官方解讀:
線程,程序執行流的最小執行單位,是行程中的實際運作單位,經常容易和進程這個概念混淆。那么,線程和進程究竟有什么區別呢?首先,進程是一個動態的過程,是一個活動的實體。簡單來說,一個應用程序的運行就可以被看做是一個進程,而線程,是運行中的實際的任務執行者。可以說,進程中包含了多個可以同時運行的線程。
2:線程的聲明周期
線程的生命周期,線程的生命周期可以利用以下的圖解來更好的理解:
3:單線程和多線程
三:線程池
1:線程池從何處而來
- 在一個應用程序中,我們需要多次使用線程,也就意味著,我們需要多次創建并銷毀線程。而創建并銷毀線程的過程勢必會消耗內存。而在Java中,內存資源是及其寶貴的,所以,我們就提出了線程池的概念
線程池:Java中開辟出了一種管理線程的概念,這個概念叫做線程池,從概念以及應用場景中,我們可以看出,線程池的好處,就是可以方便的管理線程,也可以減少內存的消耗。
2:線程池的好處
- (1) 降低資源消耗。 通過重復利用已創建的線程降低線程創建和銷毀造成的消耗。
- (2) 提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。
- (3) 提高線程的可管理性。線程是稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,調優和監控。
3:如何實現線程池
那么,我們應該如何創建一個線程池那?Java中已經提供了創建線程池的一個類:Executor類,而我們創建時,一般使用它的子類:ThreadPoolExecutor.
線程池的真正實現類是 ThreadPoolExecutor,其構造方法有如下4種:
4:線程池的使用流程
// 創建線程池 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE,MAXIMUM_POOL_SIZE,KEEP_ALIVE,TimeUnit.SECONDS,sPoolWorkQueue,sThreadFactory); // 向線程池提交任務 threadPool.execute(new Runnable() {@Overridepublic void run() {... // 線程執行的任務} }); // 關閉線程池 threadPool.shutdown(); // 設置線程池的狀態為SHUTDOWN,然后中斷所有沒有正在執行任務的線程 threadPool.shutdownNow(); // 設置線程池的狀態為 STOP,然后嘗試停止所有的正在執行或暫停任務的線程,并返回等待執行任務的列表5:線程池的工作原理
6:線程池的重要參數解讀
(1):任務隊列
(2):線程工廠(threadFactory)
線程工廠指定創建線程的方式,需要實現 ThreadFactory 接口,并實現 newThread(Runnable r) 方法。該參數可以不用指定,Executors 框架已經為我們實現了一個默認的線程工廠:
(3):拒絕策略(handler)
7:功能性線程池
嫌上面使用線程池的方法太麻煩?其實Executors已經為我們封裝好了 4 種常見的功能線程池,如下:
- 定長線程池(FixedThreadPool)
- 定時線程池(ScheduledThreadPool )
- 可緩存線程池(CachedThreadPool)
- 單線程化線程池(SingleThreadExecutor)
- newWorkStealingPool
(1): newFixedThreadPool (固定數量的線程池)
創建的源碼:
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),threadFactory); }- 特點:只有核心線程,線程數量固定,執行完立即回收,任務隊列為鏈表結構的有界隊列。
- 應用場景:控制線程最大并發數。
- 使用實例:
(2): newWorkStealingPool
這個線程池的特性從名字就可以看出 Stealing,會竊取任務。
每個線程都有自己的雙端隊列,當自己隊列的任務處理完畢之后,會去別的線程的任務隊列尾部拿任務來執行,加快任務的執行速率。
至于 ForkJoin 的話,就是分而治之,把大任務分解成一個個小任務,然后分配執行之后再總和結果,
(3): newSingleThreadExecutor (單線程池)
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())); } public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),threadFactory)); }特點:只有 1 個核心線程,無非核心線程,執行完立即回收,任務隊列為鏈表結構的有界隊列。
應用場景:不適合并發但可能引起 IO 阻塞性及影響 UI 線程響應的操作,如數據庫操作、文件操作等。
使用實例:
(4):newCachedThreadPool (可緩存的線程池)
創建方法的源碼:
public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>()); } public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(),threadFactory); }特點:無核心線程,非核心線程數量無限,執行完閑置 60s 后回收,任務隊列為不存儲元素的阻塞隊列。
應用場景:執行大量、耗時少的任務。
所以它適合用在短時間內有大量短任務的場景。如果暫無可用線程,那么來個任務就會新啟一個線程去執行這個任務,快速響應任務。
但是如果任務的時間很長,那存在的線程就很多,上下文切換就很頻繁,切換的消耗就很明顯,并且存在太多線程在內存中,也有 OOM 的風險。
使用示例:
(5): newScheduledThreadPool(定時線程池)
創建方法的源碼:private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) {super(corePoolSize, Integer.MAX_VALUE,DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,new DelayedWorkQueue()); }public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) {return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); } public ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory) {super(corePoolSize, Integer.MAX_VALUE,DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,new DelayedWorkQueue(), threadFactory); }特點:核心線程數量固定,非核心線程數量無限,執行完閑置 10ms 后回收,任務隊列為延時阻塞隊列。
應用場景:執行定時或周期性的任務。
使用示例:
參考自這篇博客
總結
以上是生活随笔為你收集整理的线程与线程池(一条龙详解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AB盘去了哪里电脑的ab盘去哪了
- 下一篇: leetcode455. 分发饼干