重寫ThreadPoolTaskExecutor

noneplus發表於2020-08-06

ThreadPoolExecutor:JDK內建執行緒池實現

ThreadPoolTaskExecutor:Spring對JDK中執行緒池做了一層封裝

參考程式碼:https://github.com/Noneplus/ConcurrentDemo

建立一個SpringBoot專案

主類開啟非同步註解

/**
 * 開啟非同步註解@EnableAsync
 */
@SpringBootApplication
@EnableAsync
public class AsyncApplication {

    public static void main(String[] args) {
        SpringApplication.run(AsyncApplication.class, args);
    }

}

建立執行緒池配置類

主類新增註解:@EnableConfigurationProperties({AsyncThreadPoolConfig.class} )

/**
 * @Description: 執行緒池引數配置
 * @Author noneplus
 * @Date 2020/8/5 19:02
 */
@ConfigurationProperties("task.pool")
public class AsyncThreadPoolConfig{

    private Integer corePoolSize;

    private Integer maxPoolSize;

    private Integer keepAliveSeconds;

    private Integer queueCapacity;

    public Integer getCorePoolSize() {
        return corePoolSize;
    }

    public void setCorePoolSize(Integer corePoolSize) {
        this.corePoolSize = corePoolSize;
    }

    public Integer getMaxPoolSize() {
        return maxPoolSize;
    }

    public void setMaxPoolSize(Integer maxPoolSize) {
        this.maxPoolSize = maxPoolSize;
    }

    public Integer getKeepAliveSeconds() {
        return keepAliveSeconds;
    }

    public void setKeepAliveSeconds(Integer keepAliveSeconds) {
        this.keepAliveSeconds = keepAliveSeconds;
    }

    public Integer getQueueCapacity() {
        return queueCapacity;
    }

    public void setQueueCapacity(Integer queueCapacity) {
        this.queueCapacity = queueCapacity;
    }
}

建立執行緒池實現類

繼承AsyncConfigurer,重寫get方法

package com.noneplus.async;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Description: 重寫Spring執行緒池
 * @Author noneplus
 * @Date 2020/8/6 10:11
 */
public class AsyncThreadPool implements AsyncConfigurer {

    @Autowired
    AsyncThreadPoolConfig asyncThreadPoolConfig;

    /**
     * ThreadPoolTaskExecutor 對比 ThreadPoolExecutor
     * ThreadPoolExecutor:JDK內建執行緒池
     * ThreadPoolTaskExecutor:Spring對ThreadPoolExecutor做了一層基礎封裝
     *
     * 相比 ThreadPoolExecutor,ThreadPoolTaskExecutor 增加了 submitListenable 方法,
     * 該方法返回 ListenableFuture 介面物件,該介面完全抄襲了 google 的 guava。
     * ListenableFuture 介面物件,增加了執行緒執行完畢後成功和失敗的回撥方法。
     * 從而避免了 Future 需要以阻塞的方式呼叫 get,然後再執行成功和失敗的方法。
     */
    @Override
    public Executor getAsyncExecutor() {

        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();


        //設定核心執行緒數,最大執行緒數,佇列容量,執行緒存活時間
        threadPoolTaskExecutor.setCorePoolSize(asyncThreadPoolConfig.getCorePoolSize());
        threadPoolTaskExecutor.setMaxPoolSize(asyncThreadPoolConfig.getMaxPoolSize());
        threadPoolTaskExecutor.setQueueCapacity(asyncThreadPoolConfig.getQueueCapacity());
        threadPoolTaskExecutor.setKeepAliveSeconds(asyncThreadPoolConfig.getKeepAliveSeconds());

        //設定執行緒名字首
        threadPoolTaskExecutor.setThreadNamePrefix("AsyncThreadPool-");

        // setRejectedExecutionHandler:當pool已經達到max size的時候,如何處理新任務
        // CallerRunsPolicy:不在新執行緒中執行任務,而是由呼叫者所在的執行緒來執行
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        // 等待所有任務結束後再關閉執行緒池
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}

建立一個測試類Controller

定義一個forTest方法

/**
 * @Description: TODO(這裡用一句話描述這個類的作用)
 * @Author noneplus
 * @Date 2020/8/5 18:33
 */
@RestController
public class TestController {

    @Autowired
    TestService testService;

    @GetMapping("/test")
    public String forTest()
    {
        testService.forTest();

        return "success";
    }
}

建立非同步Service方法

共三個執行緒,sendEmail,recoredLog和主執行緒

@Service
public class TestService {

    @Autowired
    TaskComponent taskComponent;

    public void forTest() {

        taskComponent.sendEmail();
        taskComponent.recordLog();

        for (int i = 0; i < 10; i++) {
            System.out.println("打醬油:" + i+"當前執行緒:"+Thread.currentThread().getName());
        }

    }
}

定義非同步的實現類

@Component
public class TaskComponent {

    @Async
    public void sendEmail()
    {
        for (int i = 0; i < 10; i++) {
            System.out.println("傳送簡訊中:" + i+"當前執行緒:"+Thread.currentThread().getName());
        }
    }

    @Async
    public void recordLog()
    {
        for (int i = 0; i < 10; i++) {
            System.out.println("記錄日誌中:" + i+"當前執行緒:"+ Thread.currentThread().getName());
        }
    }

}

相關文章