动态

详情 返回 返回

SpringBoot執行異步任務Async介紹 - 动态 详情

前言

本篇文章的代碼示例已放到 github 上,Git地址為:advance(記錄每一個學習過程),大家把代碼下載下來之後,全局搜索一些關鍵代碼,即可找到該文章的源碼。

大家覺得有用的話,麻煩點個star👍再走唄!

使用場景

當我們在使用SpringBoot進行開發的時候,可能會遇到一些執行異步任務的場景,如果每次執行這些異步任務都去新建一個異步線程來執行的話,那代碼就太冗餘了。幸好SpringBoot給我們提供了Async的註解,讓我們能夠很輕鬆地對這些異步任務進行執行。

使用示例

在啓動類上使用@EnableAsync註解,表示開啓異步任務

@EnableAsync
@SpringBootApplication
public class AsycnDemoApplication {

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

}

將需要執行的異步方法所在的類,加入到Spring的容器中,可以使用@Component註解

@Component
public class AsyncComponent {

}

在需要異步執行的方法上,加入@Async註解

@Component
public class AsyncComponent {
    @Async
    public void async(String str){
        System.out.println("輸入的內容是" + str + ",異步任務正在休眠5秒..");
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            System.out.println("休眠失敗");
        }
        System.out.println("輸入的內容是" + str + ",異步任務執行結束");
    }
}

在其他需要調用的地方,將這個異步方法所在的類進行注入,然後調用

@Component
public class LineRunner implements CommandLineRunner {
    @Autowired
    private AsyncComponent asyncComponent;

    @Override
    public void run(String... args) throws Exception {
        System.out.println("主線程開始");
        asyncComponent.async("今天不上班,好耶");
        asyncComponent.selfAsync();
        System.out.println("主線程結束");
    }
}

執行結果

自定義異步調用的線程池

SpringBoot默認會使用SimpleAsyncTaskExecutor線程池,這個不是真的線程池,不會重用線程,每次調用都會新建一個線程出來,用完之後就回收掉,沒起到重複利用的作用。併發量太大的話,可能會有內存溢出的風險。

因此,更加推薦開發者對異步調用的線程池進行自定義。

自定義異步線程池

@Configuration
public class ExecutorsAsyncConfig {
    @Bean(name = "asyncConfig")
    public Executor asyncConfig(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //設置核心線程數
        executor.setCorePoolSize(5);
        //設置最大線程數
        executor.setMaxPoolSize(50);
        //設置緩存的隊列
        executor.setQueueCapacity(1000);
        //設置空閒線程的超時時間
        executor.setKeepAliveSeconds(1000 * 5);
        //設置線程名稱的前綴
        executor.setThreadNamePrefix("async-config-");
        executor.initialize();
        return executor;
    }
}

編寫自定義的異步方法,其實也就就是在@Async的註解上加了線程池的bean名稱。

@Async("asyncConfig")
public void selfAsync(){
    System.out.println("我是自定義異步線程,線程池名稱:" + Thread.currentThread().getName());
    try {
        TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
        System.out.println("休眠失敗");
    }
    System.out.println("自定義異步線程休眠結束");
}

調用自定義的異步方法

asyncComponent.selfAsync();

執行結果

Async失效場景(注意事項)

  1. 調用方法和異步方法在同一個類中,會導致Async失效。
  2. 異步方法使用了static進行修飾,會導致Async失效。

Add a new 评论

Some HTML is okay.