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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[线程池] ------ 形象的描述线程池,用一个特好记的例子来记忆

發布時間:2024/7/23 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [线程池] ------ 形象的描述线程池,用一个特好记的例子来记忆 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

線程池

為了減少線程頻繁的創建和銷毀過程,引入池的概念。
將一些線程先創建好放在線程池中,每次來任務就用池中的線程執行,空閑時池中線程就等待,但不銷毀。

原始線程池的創建:
ThreadPoolExecutor executor1 = new ThreadPoolExecutor(入參);
入參有4種方式,分別對上面參數的賦值:threadFactory和handler不寫就是用默認的
(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue workQueue);
(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory);
(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue workQueue, RejectedExecutionHandler handler);
(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);

線程池的主要參數

corePoolSize:核心線程池的大小,默認最開始線程池是沒有線程的,只有當有任務來的時候會創建線程,然后這個線程以后就不會銷毀了,會一直待在線程池中等待任務。
maximumPoolSize:最大線程數。表示線程池最多可以創建多少個線程,當任務隊列放滿后還有新任務時,會嘗試將線程數提高到最大線程數。
keepAliveTime:非核心線程空閑銷毀倒計時,即當線程池中的線程數,大于核心線程數時,針對多出來的線程(就叫非核心線程),如果空閑時間超過這個時間,就銷毀。
unit:keepAliveTime參數的單位,可以是:

TimeUnit.DAYS; //天 TimeUnit.HOURS; //小時 TimeUnit.MINUTES; //分鐘 TimeUnit.SECONDS; //秒 TimeUnit.MILLISECONDS; //毫秒 TimeUnit.MICROSECONDS; //微妙 TimeUnit.NANOSECONDS; //納秒

workQueue:阻塞隊列,存放要等待的任務,也叫任務隊列。可以是:

ArrayBlockingQueue LinkedBlockingQueue SynchronousQueue

threadFactory:線程工廠,用來創建線程。
handler:拒絕任務的策略,當線程數達到maximumPoolSize,并且workQueue也被任務放滿時,再來就會被拒絕,可選的拒絕策略有:

ThreadPoolExecutor.AbortPolicy:丟棄任務并拋出RejectedExecutionException異常。 ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。 ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程)。 ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務。

我們舉個實際例子來記憶這些參數(重要)

例子的場景是火車票售票大廳,乘客買票的例子。
火車票售票大廳,往往會開多個窗口來賣票,我們把一個個乘客比作是一個個任務,把一個個售票窗口比作一個個線程

假設某縣火車票售票大廳,第一天營業,剛上班,一個窗口也沒開,這就是線程池的初始化
這時候來了第一位乘客a,同時喚醒第一個售票窗口A,開始辦理業務。
此時馬上又來了一個乘客b,窗口A正在被占用,于是又開啟第二個窗口B為乘客b辦理業務。
我們已知這個火車站就2個正式窗口,相當于corePoolSize=2

那么后面來的人就要開始等了,我們把售票大廳的凳子比作任務隊列,比如只有3個凳子,即任務隊列最多容納3個任務
與此同時,前面的乘客ab都沒辦理完,所以窗口A和窗口B都被占用了,后面又連續來了3個乘客cde,剛好,cde都坐在了凳子上,那么凳子就被坐滿了。

此時,fg二位乘客也跟著來了,那么此時2個正式窗口被占,3個凳子也被占,于是火車站管理員臨時又加了兩個窗口,
這兩個臨時窗口,就相當于非核心線程,前面那兩個AB窗口,就是正式窗口,就是核心線程,總共最多開4個窗口,那么就有maximumPoolSize=4
注意了,這里是等到正式窗口被占完,凳子也被坐滿,才開的臨時窗口。即核心線程占完,隊列填滿,才會嘗試使用非核心線程做任務。

此時7位乘客,算是把這個售票大廳的資源給用完了,后面又來了乘客h,他就進不去了,要么把他趕出去算是拋個異常,要么他就一直著嘗試進去算是重試,等等拒絕他的策略,這就用到了拒絕策略

后來慢慢的,前面的乘客都把票買了,凳子也空了,臨時窗口也空閑了,等了1個小時也沒有任務了,管理員就把臨時窗口又撤銷了,只留兩個正式窗口。這個1小時就是keepAliveTime=1,單位unit是小時TimeUnit.HOURS

常用的線程池使用方式:

常用的線程池,不用new ThreadPoolExecutor(入參)的方式創建,是用Executors來創建的。

可回收緩存線程池(corePoolSize = 0;maximumPoolSize = Integer.MAX_VALUE;線程空閑后都可以銷毀,但要注意設置合適的回收時間)

Executors.newCachedThreadPool();
繼續上面的火車站的例子,這個情況就相當于火車站沒有正式窗口,全是臨時窗口,有人就開臨時窗口,沒人就關了窗口。

固定線程池(corePoolSize = maximumPoolSize)

Executors.newFixedThreadPool(n);
這個情況相當于沒有臨時窗口了,但是凳子特別多,即workQueue.size() = Integer.MAX_VALUE ,正式窗口和凳子都滿后,再來的人就直接拒絕策略給拒絕了。

單線程線程池(corePoolSize = maximumPoolSize = 1,串行用)

Executors.newSingleThreadExecutor();
這個情況就是只有一個正式窗口,其他的和固定線程池一樣。

可調度線程池(支持定時與周期性任務)

Executors.newScheduledThreadPool(n);

實戰例子

package com.zs.test;import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.concurrent.*;/*** @author zhangshuai**/ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring-config-test.xml") public class TestThreadPool {Logger logger = LoggerFactory.getLogger(TestThreadPool.class);final static CountDownLatch countDownLatch = new CountDownLatch(14);private ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 6, 3, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(5));private ExecutorService executor2 = Executors.newCachedThreadPool();private ExecutorService executor3 = Executors.newSingleThreadExecutor();private ExecutorService executor4 = Executors.newFixedThreadPool(3);private ExecutorService executor5 = Executors.newScheduledThreadPool(2);@Testpublic void test() throws InterruptedException {for(int i=0;i<14;i++){MyTestTask myTestTask = new MyTestTask(i);executor.execute(myTestTask);logger.info("線程池中線程數目:"+executor.getPoolSize()+",隊列中等待執行的任務數目:"+executor.getQueue().size()+",已執行完別的任務數目:"+executor.getCompletedTaskCount());if(i == 6){//總共14個任務,核心線程數設置5個,最大線程數6個,// 我們讓前7個任務執行完等待10秒,是為了讓設置的銷毀非核心線程的時間3秒起作用。//后面就能看到非核心線程的創建,銷毀和再次創建。Thread.sleep(10000);}}executor.shutdown();countDownLatch.await();}class MyTestTask implements Runnable {private int taskNum;public MyTestTask(int num) {this.taskNum = num;}@Overridepublic void run() {try {logger.info("正在執行的taskNum: "+taskNum);try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}logger.info("task: "+taskNum+"執行完畢");} catch (Exception e) {e.printStackTrace();}finally{countDownLatch.countDown();}}} }

執行完的結果是:

先創建5個線程執行5個任務01234
3秒后01234執行完
接著創建56任務
與此同時主線程執行sleep10秒
3秒后56任務執行完
當主線程醒來,再次執行后面的任務。

[pool-1-thread-1] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 0 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:1,隊列中等待執行的任務數目:0,已執行完別的任務數目:0 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:2,隊列中等待執行的任務數目:0,已執行完別的任務數目:0 [pool-1-thread-2] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 1 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:3,隊列中等待執行的任務數目:0,已執行完別的任務數目:0 [pool-1-thread-3] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 2 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:4,隊列中等待執行的任務數目:0,已執行完別的任務數目:0 [pool-1-thread-4] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 3 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:0,已執行完別的任務數目:0 [pool-1-thread-5] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 4 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:1,已執行完別的任務數目:0 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:2,已執行完別的任務數目:0[pool-1-thread-1] INFO com.zs.test.TestThreadPool - task: 0執行完畢 [pool-1-thread-2] INFO com.zs.test.TestThreadPool - task: 1執行完畢 [pool-1-thread-4] INFO com.zs.test.TestThreadPool - task: 3執行完畢 [pool-1-thread-3] INFO com.zs.test.TestThreadPool - task: 2執行完畢 [pool-1-thread-5] INFO com.zs.test.TestThreadPool - task: 4執行完畢[pool-1-thread-1] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 5 [pool-1-thread-2] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 6 [pool-1-thread-1] INFO com.zs.test.TestThreadPool - task: 5執行完畢 [pool-1-thread-2] INFO com.zs.test.TestThreadPool - task: 6執行完畢[main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:1,已執行完別的任務數目:7 [pool-1-thread-4] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 7 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:1,已執行完別的任務數目:7 [pool-1-thread-3] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 8 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:1,已執行完別的任務數目:7 [pool-1-thread-5] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 9 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:1,已執行完別的任務數目:7 [pool-1-thread-2] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 10 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:1,已執行完別的任務數目:7 [pool-1-thread-1] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 11 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:1,已執行完別的任務數目:7 [main] INFO com.zs.test.TestThreadPool - 線程池中線程數目:5,隊列中等待執行的任務數目:2,已執行完別的任務數目:7 [pool-1-thread-4] INFO com.zs.test.TestThreadPool - task: 7執行完畢 [pool-1-thread-3] INFO com.zs.test.TestThreadPool - task: 8執行完畢 [pool-1-thread-5] INFO com.zs.test.TestThreadPool - task: 9執行完畢 [pool-1-thread-2] INFO com.zs.test.TestThreadPool - task: 10執行完畢 [pool-1-thread-1] INFO com.zs.test.TestThreadPool - task: 11執行完畢 [pool-1-thread-5] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 12 [pool-1-thread-4] INFO com.zs.test.TestThreadPool - 正在執行的taskNum: 13 [pool-1-thread-5] INFO com.zs.test.TestThreadPool - task: 12執行完畢 [pool-1-thread-4] INFO com.zs.test.TestThreadPool - task: 13執行完畢

總結

以上是生活随笔為你收集整理的[线程池] ------ 形象的描述线程池,用一个特好记的例子来记忆的全部內容,希望文章能夠幫你解決所遇到的問題。

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