自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官:說說線程池的工作原理?

開發(fā) 前端
Spring 項(xiàng)目中,會(huì)使用代碼可讀性更高的 ThreadPoolTaskExecutor 來創(chuàng)建線程池,雖然它的底層也是通過 ThreadPoolExecutor 來實(shí)現(xiàn)的,但 ThreadPoolTaskExecutor 可讀性更高,因?yàn)樗恍枰跇?gòu)造方法中設(shè)置參數(shù),而是通過屬性設(shè)置的方式來設(shè)置參數(shù)的,所以可讀性更高。

線程池的底層是基于線程和任務(wù)隊(duì)列來實(shí)現(xiàn)的,創(chuàng)建線程池的創(chuàng)建方式通常有以下兩種:

  1. 普通 Java 項(xiàng)目,使用 ThreadPoolExecutor 來創(chuàng)建線程池,這點(diǎn)《阿里巴巴Java開發(fā)手冊》中也有說明,如下圖所示:

圖片圖片

  1. Spring 項(xiàng)目中,會(huì)使用代碼可讀性更高的 ThreadPoolTaskExecutor 來創(chuàng)建線程池,雖然它的底層也是通過 ThreadPoolExecutor 來實(shí)現(xiàn)的,但 ThreadPoolTaskExecutor 可讀性更高,因?yàn)樗恍枰跇?gòu)造方法中設(shè)置參數(shù),而是通過屬性設(shè)置的方式來設(shè)置參數(shù)的,所以可讀性更高。

Spring 內(nèi)置的線程池 ThreadPoolTaskExecutor 的使用示例如下:

@Configuration
public class AsyncConfig {
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心線程數(shù)
        executor.setCorePoolSize(5);
        // 最大線程數(shù)
        executor.setMaxPoolSize(10);
        // 隊(duì)列容量
        executor.setQueueCapacity(20);
        // 線程池維護(hù)線程所允許的空閑時(shí)間
        executor.setKeepAliveSeconds(60);
        // 線程池對拒絕任務(wù)(無線程可用)的處理策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化
        executor.initialize();
        return executor;
    }
}

一、線程池工作流程

當(dāng)有任務(wù)來了之后,線程池的執(zhí)行流程是這樣的:

  1. 先判斷當(dāng)前線程數(shù)是否大于核心線程數(shù),如果結(jié)果為 false,則新建線程并執(zhí)行任務(wù)。
  2. 如果大于核心線程數(shù),則判斷任務(wù)隊(duì)列是否已滿,如果結(jié)果為 false,則把任務(wù)添加到任務(wù)隊(duì)列中等待線程執(zhí)行。
  3. 如果任務(wù)隊(duì)列已滿,則判斷當(dāng)前線程數(shù)量是否超過最大線程數(shù),如果結(jié)果為 false,則新建線程執(zhí)行此任務(wù)。
  4. 如果超過最大線程數(shù),則將執(zhí)行線程池的拒絕策略。

如下圖所示:

圖片圖片

二、拒絕策略

當(dāng)線程池?zé)o法接受新任務(wù)時(shí),會(huì)觸發(fā)拒絕策略,內(nèi)置的拒絕策略有四種:

  1. AbortPolicy:默認(rèn)策略,直接拋出 RejectedExecutionException 異常。
  2. CallerRunsPolicy:由調(diào)用者線程執(zhí)行任務(wù)。
  3. DiscardPolicy:默默地丟棄任務(wù),沒有任何異常拋出。
  4. DiscardOldestPolicy:嘗試拋棄隊(duì)列中最舊的任務(wù),然后重新嘗試提交當(dāng)前任務(wù)。

除了內(nèi)置的拒絕策略之外,我們還可以設(shè)置自定義拒絕策略,它的實(shí)現(xiàn)如下:

import java.util.concurrent.RejectedExecutionHandler;  
import java.util.concurrent.ThreadPoolExecutor;  
  
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {  
  
    @Override  
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {  
        // 在這里處理拒絕的任務(wù)  
        System.err.println("任務(wù)被拒絕執(zhí)行: " + r.toString());  
        // 可以選擇記錄日志、拋出自定義異?;虿扇∑渌胧? 
        // 例如,可以將任務(wù)保存到某個(gè)隊(duì)列中,稍后再嘗試重新執(zhí)行  
    }  
}

使用自定義拒絕策略:

import java.util.concurrent.ArrayBlockingQueue;  
import java.util.concurrent.ThreadPoolExecutor;  
import java.util.concurrent.TimeUnit;  
  
public class ThreadPoolDemo {  
  
    public static void main(String[] args) {  
        // 配置線程池參數(shù)  
        int corePoolSize = 5;  
        int maximumPoolSize = 10;  
        long keepAliveTime = 60L;  
        TimeUnit unit = TimeUnit.SECONDS;  
        int queueCapacity = 25;  
  
        // 創(chuàng)建一個(gè)阻塞隊(duì)列  
        ArrayBlockingQueue<Runnable> workQueue = 
            new ArrayBlockingQueue<>(queueCapacity);  
  
        // 創(chuàng)建 ThreadPoolExecutor 實(shí)例  
        ThreadPoolExecutor executor = new ThreadPoolExecutor(  
                corePoolSize,  
                maximumPoolSize,  
                keepAliveTime,  
                unit,  
                workQueue,  
                new CustomRejectedExecutionHandler() // 使用自定義的拒絕策略  
        );  
  
        // 提交任務(wù)  
        for (int i = 0; i < 50; i++) {  
            final int taskId = i;  
            executor.execute(() -> {  
                System.out.println("執(zhí)行任務(wù): " + taskId + " 由線程 " + Thread.currentThread().getName() + " 執(zhí)行");  
                try {  
                    Thread.sleep(1000); // 模擬耗時(shí)任務(wù)  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            });  
        }  
  
        // 關(guān)閉線程池(這不會(huì)立即停止所有正在執(zhí)行的任務(wù))  
        executor.shutdown();  
    }  
}

課后反思

實(shí)際項(xiàng)目中線程池會(huì)使用哪種拒絕策略?為什么?線程池是通過什么機(jī)制來創(chuàng)建線程的?線程池創(chuàng)建線程時(shí)可以設(shè)置哪些屬性?

責(zé)任編輯:武曉燕 來源: Java中文社群
相關(guān)推薦

2024-06-04 09:02:03

2024-09-12 08:35:06

2024-08-22 10:39:50

@Async注解代理

2024-03-05 10:33:39

AOPSpring編程

2024-11-19 15:13:02

2023-12-27 18:16:39

MVCC隔離級(jí)別幻讀

2025-04-16 00:00:01

JWT客戶端存儲(chǔ)加密令

2024-03-14 14:56:22

反射Java數(shù)據(jù)庫連接

2024-07-31 08:28:37

DMAIOMMap

2024-12-06 07:00:00

2024-02-29 16:49:20

volatileJava并發(fā)編程

2024-09-20 08:36:43

零拷貝數(shù)據(jù)傳輸DMA

2024-03-22 06:56:24

零拷貝技術(shù)數(shù)據(jù)傳輸數(shù)據(jù)拷貝

2024-08-29 16:30:27

2024-08-12 17:36:54

2021-06-07 17:12:22

線程安全Atomic

2025-02-28 00:00:00

2024-03-01 11:33:31

2024-12-04 14:45:14

零拷貝技術(shù)CPU 拷貝Zero-copy

2024-03-28 10:37:44

IoC依賴注入依賴查找
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)