日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

說一下線程池的核心參數(shù),線程池的執(zhí)行原理

來源: 責(zé)編: 時(shí)間:2023-11-30 09:28:42 273觀看
導(dǎo)讀1.線程池的核心參數(shù)線程池七大核心參數(shù)如下所示:public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable>

1.線程池的核心參數(shù)

線程池七大核心參數(shù)如下所示:VC928資訊網(wǎng)——每日最新資訊28at.com

public ThreadPoolExecutor(int corePoolSize,        int maximumPoolSize,         long keepAliveTime,         TimeUnit unit,         BlockingQueue<Runnable> workQueue,        ThreadFactory threadFactory,        RejectedExecutionHandler handler        )
  • corePoolSize: 核心線程數(shù)目
  • maximumPoolSize: 最大線程數(shù)目 = (核心線程+救急線程的最大數(shù)目)
  • keepAliveTime: 生存時(shí)間 - 救急線程的生存時(shí)間,生存時(shí)間內(nèi)沒有新任務(wù),此線程資源會(huì)釋放
  • unit: 時(shí)間單位 , 救急線程的生存時(shí)間單位,如秒、毫秒等
  • workQueue: 當(dāng)沒有空閑核心線程時(shí),新來任務(wù)會(huì)加入到此隊(duì)列排隊(duì),隊(duì)列滿會(huì)創(chuàng)建救急線程執(zhí)行任務(wù)
  • **threadFactory: 線程工廠 , 可以定制線程對(duì)象的創(chuàng)建,例如設(shè)置線程名字、是否是守護(hù)線程等
  • handler 拒絕策略 - 當(dāng)所有線程都在繁忙,workQueue 也放滿時(shí),會(huì)觸發(fā)拒絕策略

思考:線程池的執(zhí)行原理知道嘛?

2. 線程池的執(zhí)行原理

1: 任務(wù)在提交的時(shí)候,首先判斷核心線程數(shù)是否已滿,如果沒有滿則直接添加到工作線程執(zhí)行VC928資訊網(wǎng)——每日最新資訊28at.com

2: 如果核心線程數(shù)滿了,則判斷阻塞隊(duì)列是否已滿,如果沒有滿,當(dāng)前任務(wù)存入阻塞隊(duì)列VC928資訊網(wǎng)——每日最新資訊28at.com

3:如果阻塞隊(duì)列也滿了,則判斷線程數(shù)是否小于最大線程數(shù),如果滿足條件,則使用臨時(shí)線程執(zhí)行任務(wù)如果核心或臨時(shí)線程執(zhí)行完成任務(wù)后會(huì)檢查阻塞隊(duì)列中是否有需要執(zhí)行的線程,如果有,則使用非核心線程執(zhí)行任務(wù)VC928資訊網(wǎng)——每日最新資訊28at.com

4:如果所有線程都在忙著(核心線程+臨時(shí)線程),則走拒絕策略VC928資訊網(wǎng)——每日最新資訊28at.com

VC928資訊網(wǎng)——每日最新資訊28at.com

思考:拒絕策略有哪些?

1.AbortPolicy:直接拋出異常,默認(rèn)策略VC928資訊網(wǎng)——每日最新資訊28at.com

2.CallerRunsPolicy:用調(diào)用者所在的線程來執(zhí)行任務(wù)VC928資訊網(wǎng)——每日最新資訊28at.com

3.DiscardOldestPolicy:丟棄阻塞隊(duì)列中靠最前的任務(wù),并執(zhí)行當(dāng)前任務(wù)VC928資訊網(wǎng)——每日最新資訊28at.com

4.DiscardPolicy:直接丟棄任務(wù)VC928資訊網(wǎng)——每日最新資訊28at.com

案例:VC928資訊網(wǎng)——每日最新資訊28at.com

public class TestThreadPoolExecutor {    static class MyTask implements Runnable {        private final String name;        private final long duration;        public MyTask(String name) {            this(name, 0);        }        public MyTask(String name, long duration) {            this.name = name;            this.duration = duration;        }        @Override        public void run() {            try {                LoggerUtils.get("myThread").debug("running..." + this);                Thread.sleep(duration);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        @Override        public String toString() {            return "MyTask(" + name + ")";        }    }    public static void main(String[] args) throws InterruptedException {        AtomicInteger c = new AtomicInteger(1);        ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(2);        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(                2,                3,                0,                TimeUnit.MILLISECONDS,                queue,                r -> new Thread(r, "myThread" + c.getAndIncrement()),                new ThreadPoolExecutor.AbortPolicy());        showState(queue, threadPool);        threadPool.submit(new MyTask("1", 3600000));        showState(queue, threadPool);        threadPool.submit(new MyTask("2", 3600000));        showState(queue, threadPool);        threadPool.submit(new MyTask("3"));        showState(queue, threadPool);        threadPool.submit(new MyTask("4"));        showState(queue, threadPool);        threadPool.submit(new MyTask("5",3600000));        showState(queue, threadPool);        threadPool.submit(new MyTask("6"));        showState(queue, threadPool);    }    private static void showState(ArrayBlockingQueue<Runnable> queue, ThreadPoolExecutor threadPool) {        try {            Thread.sleep(300);        } catch (InterruptedException e) {            e.printStackTrace();        }        List<Object> tasks = new ArrayList<>();        for (Runnable runnable : queue) {            try {                Field callable = FutureTask.class.getDeclaredField("callable");                callable.setAccessible(true);                Object adapter = callable.get(runnable);                Class<?> clazz = Class.forName("java.util.concurrent.Executors$RunnableAdapter");                Field task = clazz.getDeclaredField("task");                task.setAccessible(true);                Object o = task.get(adapter);                tasks.add(o);            } catch (Exception e) {                e.printStackTrace();            }        }        LoggerUtils.main.debug("pool size: {}, queue: {}", threadPool.getPoolSize(), tasks);    }}

思考:線程池中有哪些常見的阻塞隊(duì)列?

3. 常見阻塞隊(duì)列

workQueue: 當(dāng)沒有空閑核心線程時(shí),新來任務(wù)會(huì)加入到此隊(duì)列排隊(duì),隊(duì)列滿會(huì)創(chuàng)建救急線程執(zhí)行任務(wù)。VC928資訊網(wǎng)——每日最新資訊28at.com

比較常見的有4個(gè),用的最多是ArrayBlockingQueue和LinkedBlockingQueue。VC928資訊網(wǎng)——每日最新資訊28at.com

  • 1.ArrayBlockingQueue:基于數(shù)組結(jié)構(gòu)的有界阻塞隊(duì)列
  • 2.LinkedBlockingQueue:基于鏈表結(jié)構(gòu)的有界阻塞隊(duì)列
  • 3.DelayedWorkQueue :是一個(gè)優(yōu)先級(jí)隊(duì)列,它可以保證每次出隊(duì)的任務(wù)都是當(dāng)前隊(duì)列中執(zhí)行時(shí)間最靠前的
  • 4.SynchronousQueue:不存儲(chǔ)元素的阻塞隊(duì)列,每個(gè)插入操作都必須等待一個(gè)移出操作

3.1. ArrayBlockingQueue的LinkedBlockingQueue區(qū)別

inkedBlockingQueue**VC928資訊網(wǎng)——每日最新資訊28at.com

ArrayBlockingQueueVC928資訊網(wǎng)——每日最新資訊28at.com

默認(rèn)無界,支持有界VC928資訊網(wǎng)——每日最新資訊28at.com

強(qiáng)制有界VC928資訊網(wǎng)——每日最新資訊28at.com

底層是鏈表VC928資訊網(wǎng)——每日最新資訊28at.com

底層是數(shù)組VC928資訊網(wǎng)——每日最新資訊28at.com

是懶惰的,創(chuàng)建節(jié)點(diǎn)的時(shí)候添加數(shù)據(jù)VC928資訊網(wǎng)——每日最新資訊28at.com

提前初始化 Node  數(shù)組VC928資訊網(wǎng)——每日最新資訊28at.com

入隊(duì)會(huì)生成新 NodeVC928資訊網(wǎng)——每日最新資訊28at.com

Node需要是提前創(chuàng)建好的VC928資訊網(wǎng)——每日最新資訊28at.com

兩把鎖(頭尾)VC928資訊網(wǎng)——每日最新資訊28at.com

一把鎖VC928資訊網(wǎng)——每日最新資訊28at.com

左邊是LinkedBlockingQueue加鎖的方式,右邊是ArrayBlockingQueue加鎖的方式VC928資訊網(wǎng)——每日最新資訊28at.com

VC928資訊網(wǎng)——每日最新資訊28at.com

  • LinkedBlockingQueue:讀和寫各有一把鎖,性能相對(duì)較好
  • ArrayBlockingQueue:只有一把鎖,讀和寫公用,性能相對(duì)于LinkedBlockingQueue差一些

4. 線程池的種類有哪些

在java.util.concurrent.Executors類中提供了大量創(chuàng)建連接池的靜態(tài)方法,常見就有四種VC928資訊網(wǎng)——每日最新資訊28at.com

1.創(chuàng)建使用固定線程數(shù)的線程池VC928資訊網(wǎng)——每日最新資訊28at.com

public static ExecutorService newFixedThreadPool(int nThreads) {        return new ThreadPoolExecutor(nThreads,                                       0L,                                       TimeUnit.MILLISECONDS,                                       new LinkedBlockingQueue<>());    }
  • 核心線程數(shù)與最大線程數(shù)一樣,沒有救急線程
  • 阻塞隊(duì)列是LinkedBlockingQueue,最大容量為Integer.MAX_VALUE
  • 適用場(chǎng)景:適用于任務(wù)量已知,相對(duì)耗時(shí)的任務(wù)
  • 案例
/** * @author springboot葵花寶典 * @description: TODO */public class FixedThreadPoolTest {    static class FixedThreadDemo implements Runnable{        @Override        public void run() {            String name = Thread.currentThread().getName();            for (int i = 0; i < 2; i++) {                System.out.println(name + ":" + i);            }        }    }    public static void main(String[] args) throws InterruptedException {        //創(chuàng)建一個(gè)固定大小的線程池,核心線程數(shù)和最大線程數(shù)都是3        ExecutorService executorService = Executors.newFixedThreadPool(3);        for (int i = 0; i < 5; i++) {            executorService.submit(new FixedThreadDemo());            Thread.sleep(10);        }        executorService.shutdown();    }}

2.單線程化的線程池,它只會(huì)用唯一的工作線程來執(zhí)行任 務(wù),保證所有任務(wù)按照指定順序(FIFO)執(zhí)行VC928資訊網(wǎng)——每日最新資訊28at.com

public static ExecutorService newSingleThreadExecutor() {        return new FinalizableDelegatedExecutorService        (new ThreadPoolExecutor(1,         1,         0L,        TimeUnit.MILLISECONDS,         new LinkedBlockingQueue<>()));    }
  • 核心線程數(shù)和最大線程數(shù)都是1
  • 阻塞隊(duì)列是LinkedBlockingQueue,最大容量為Integer.MAX_VALUE
  • 適用場(chǎng)景:適用于按照順序執(zhí)行的任務(wù)
  • 案例
/** * @author springboot葵花寶典 * @description: TODO */public class NewSingleThreadTest {    static int count = 0;    static class Demo implements Runnable {        @Override        public void run() {            count++;            System.out.println(Thread.currentThread().getName() + ":" + count);        }    }    public static void main(String[] args) throws InterruptedException {        //單個(gè)線程池,核心線程數(shù)和最大線程數(shù)都是1        ExecutorService exec = Executors.newSingleThreadExecutor();        for (int i = 0; i < 10; i++) {            exec.execute(new Demo());            Thread.sleep(5);        }        exec.shutdown();    }}
  1. 可緩存線程池
public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0,                                    Integer.MAX_VALUE,                                     60L,                                    TimeUnit.SECONDS, n                                    ew SynchronousQueue<>());    }
  • 核心線程數(shù)為0
  • 最大線程數(shù)是Integer.MAX_VALUE
  • 阻塞隊(duì)列為SynchronousQueue:不存儲(chǔ)元素的阻塞隊(duì)列,每個(gè)插入操作都必須等待一個(gè)移出操作
  • 適用場(chǎng)景:適合任務(wù)數(shù)比較密集,但每個(gè)任務(wù)執(zhí)行時(shí)間較短的情況
  • 案例:
/** * @author springboot葵花寶典 * @description: TODO */public class CachedThreadPoolTest {    static class Demo implements Runnable {        @Override        public void run() {            String name = Thread.currentThread().getName();            try {                //修改睡眠時(shí)間,模擬線程執(zhí)行需要花費(fèi)的時(shí)間                Thread.sleep(100);                System.out.println(name + "執(zhí)行完了");            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) throws InterruptedException {        //創(chuàng)建一個(gè)緩存的線程,沒有核心線程數(shù),最大線程數(shù)為Integer.MAX_VALUE        ExecutorService exec = Executors.newCachedThreadPool();        for (int i = 0; i < 10; i++) {            exec.execute(new Demo());            Thread.sleep(1);        }        exec.shutdown();    }}

4.提供了“延遲”和“周期執(zhí)行”功能的ThreadPoolExecutor

public ScheduledThreadPoolExecutor(int corePoolSize,                                   ThreadFactory threadFactory,                                   RejectedExecutionHandler handler{ super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue(), threadFactory, handler);                     }
  • 適用場(chǎng)景:有定時(shí)和延遲執(zhí)行的任務(wù)
  • 案例
/** * @author springboot葵花寶典 * @description: TODO */public class ScheduledThreadPoolTest {    static class Task implements Runnable {        @Override        public void run() {            try {                String name = Thread.currentThread().getName();                System.out.println(name + ", 開始:" + new Date());                Thread.sleep(1000);                System.out.println(name + ", 結(jié)束:" + new Date());            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) throws InterruptedException {        //按照周期執(zhí)行的線程池,核心線程數(shù)為2,最大線程數(shù)為Integer.MAX_VALUE        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);        System.out.println("程序開始:" + new Date());        /**         * schedule 提交任務(wù)到線程池中         * 第一個(gè)參數(shù):提交的任務(wù)         * 第二個(gè)參數(shù):任務(wù)執(zhí)行的延遲時(shí)間         * 第三個(gè)參數(shù):時(shí)間單位         */        scheduledThreadPool.schedule(new Task(), 0, TimeUnit.SECONDS);        scheduledThreadPool.schedule(new Task(), 1, TimeUnit.SECONDS);        scheduledThreadPool.schedule(new Task(), 5, TimeUnit.SECONDS);        Thread.sleep(5000);        // 關(guān)閉線程池        scheduledThreadPool.shutdown();    }}

5. 線程池面試題

面試官:線程池的核心參數(shù)有哪些?

候選人:VC928資訊網(wǎng)——每日最新資訊28at.com

在線程池中一共有7個(gè)核心參數(shù):VC928資訊網(wǎng)——每日最新資訊28at.com

  1. corePoolSize 核心線程數(shù)目 - 池中會(huì)保留的最多線程數(shù)
  2. maximumPoolSize 最大線程數(shù)目 - 核心線程+救急線程的最大數(shù)目
  3. keepAliveTime 生存時(shí)間 - 救急線程的生存時(shí)間,生存時(shí)間內(nèi)沒有新任務(wù),此線程資源會(huì)釋放
  4. unit 時(shí)間單位 - 救急線程的生存時(shí)間單位,如秒、毫秒等
  5. workQueue - 當(dāng)沒有空閑核心線程時(shí),新來任務(wù)會(huì)加入到此隊(duì)列排隊(duì),隊(duì)列滿會(huì)創(chuàng)建救急線程執(zhí)行任務(wù)
  6. threadFactory 線程工廠 - 可以定制線程對(duì)象的創(chuàng)建,例如設(shè)置線程名字、是否是守護(hù)線程等
  7. handler 拒絕策略 - 當(dāng)所有線程都在繁忙,workQueue 也放滿時(shí),會(huì)觸發(fā)拒絕策略

在拒絕策略中又有4中拒絕策略VC928資訊網(wǎng)——每日最新資訊28at.com

  • 第一種是AbortPolicy,之際拋異常
  • 第二種是CallerRunsPolicy由調(diào)用者執(zhí)行任務(wù)
  • 第三是DiscardOldestPolicy丟棄當(dāng)前的任務(wù)
  • 第四是DiscardPolicy丟棄最早排隊(duì)任務(wù)。默認(rèn)是直接拋異常。

面試官:線程池的執(zhí)行原理知道嗎?

候選人:VC928資訊網(wǎng)——每日最新資訊28at.com

首先判斷線程池里的核心線程是否都在執(zhí)行任務(wù),如果不是則創(chuàng)建一個(gè)新的工作線程來執(zhí)行任務(wù)。如果核心線程都在執(zhí)行任務(wù),則線程池判斷工作隊(duì)列是否已滿,如果工作隊(duì)列沒有滿,則將新提交的任務(wù)存儲(chǔ)在這個(gè)工作隊(duì) 列里。如果工作隊(duì)列滿了,則判斷線程池里的線程是否都處于工作狀態(tài),如果沒有,則創(chuàng)建一個(gè)新的工作線程來執(zhí)行任 務(wù)。如果已經(jīng)滿了,則交給拒絕策略來處理這個(gè)任務(wù)。VC928資訊網(wǎng)——每日最新資訊28at.com

面試官:線程池的種類有哪些?

候選人:VC928資訊網(wǎng)——每日最新資訊28at.com

在jdk中默認(rèn)提供了4中方式創(chuàng)建線程池VC928資訊網(wǎng)——每日最新資訊28at.com

  • 第一個(gè)是:newCachedThreadPool創(chuàng)建一個(gè)可緩存線程池,如果線程池長度超過處理需要,可靈活回 收空閑線程,若無可回收,則新建線程。
  • 第二個(gè)是:newFixedThreadPool 創(chuàng)建一個(gè)定長線程池,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列 中等待。
  • 第三個(gè)是:newScheduledThreadPool 創(chuàng)建一個(gè)定長線程池,支持定時(shí)及周期性任務(wù)執(zhí)行。
  • 第四個(gè)是:newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來執(zhí)行任 務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行。

本文鏈接:http://www.www897cc.com/showinfo-26-35298-0.html說一下線程池的核心參數(shù),線程池的執(zhí)行原理

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 比亞迪面試,全程八股!

下一篇: 線程包括哪些狀態(tài),狀態(tài)之間是如何變化?

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 田阳县| 密云县| 连云港市| 波密县| 白城市| 马尔康县| 杭州市| 饶阳县| 彩票| 修武县| 瑞丽市| 新建县| 时尚| 即墨市| 博罗县| 哈密市| 新乐市| 明水县| 泰兴市| 肇东市| 府谷县| 天全县| 临桂县| 邵阳市| 凭祥市| 凌云县| 衡阳县| 苍南县| 土默特右旗| 苍溪县| 股票| 玉田县| 通许县| 南宫市| 西畴县| 舒兰市| 扎囊县| 辽源市| 尤溪县| 蒙自县| 岑巩县|