Springboot學習筆記(一)-線程池的簡化及使用

工作中經常涉及異步任務,通常是使用多線程技術,比如線程池ThreadPoolExecutor,它的執行規則如下:

在Springboot中對其進行了簡化處理,只需要配置一個類型爲java.util.concurrent.TaskExecutor或其子類的bean,並在配置類或直接在程序入口類上聲明註解@EnableAsync

調用也簡單,在由Spring管理的對象的方法上標註註解@Async,顯式調用即可生效。

一般使用Spring提供的ThreadPoolTaskExecutor類。

聲明

@Configuration
@EnableAsync
public class BeanConfig {

    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 設置核心線程數
        executor.setCorePoolSize(5);
        // 設置最大線程數
        executor.setMaxPoolSize(10);
        // 設置隊列容量
        executor.setQueueCapacity(20);
        // 設置線程活躍時間(秒)
        executor.setKeepAliveSeconds(60);
        // 設置默認線程名稱
        executor.setThreadNamePrefix("hello-");
        // 設置拒絕策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任務結束後再關閉線程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }
}

調用

@Component
public class Hello {
    @Async
    public void sayHello(String name) {
        LoggerFactory.getLogger(Hello.class).info(name + ":Hello World!");
    }
}

測試


從打印日誌中可以看出線程池已經正常工作了。

進階

有時候我們不止希望異步執行任務,還希望任務執行完成後會有一個返回值,在java中提供了Future泛型接口,用來接收任務執行結果,springboot也提供了此類支持,使用實現了ListenableFuture接口的類如AsyncResult來作爲返回值的載體。比如上例中,我們希望返回一個類型爲String類型的值,可以將返回值改造爲:

    @Async
    public ListenableFuture<String> sayHello(String name) {
        String res = name + ":Hello World!";
        LoggerFactory.getLogger(Hello.class).info(res);
        return new AsyncResult<>(res);
    }

調用返回值:

    @Autowired
    private Hello hello;

    // 阻塞調用
    hello.sayHello("yan").get();
    // 限時調用
    hello.sayHello("yan").get(1, TimeUnit.SECONDS)

補充

實際上,@Async還有一個參數,通過Bean名稱來指定調用的線程池-比如上例中設置的線程池參數不滿足業務需求,可以另外定義合適的線程池,調用時指明使用這個線程池-缺省時springboot會優先使用名稱爲'taskExecutor'的線程池,如果沒有找到,纔會使用其他類型爲TaskExecutor或其子類的線程池。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章