@Async,@EnableAsync,AsyncConfigurer 自定義線程池

1. @Async

在spring中,可以通過@EnableAsync + @Async兩個註解非常快捷的實現異步。步驟如下:

啓動類加上: @EnableAsync註解 並且在service上加上@Async註解

@SpringBootApplication(
        exclude = {CodecsAutoConfiguration.class},
        scanBasePackages = {
        		"com.arvato.config",
        		"com.arvato.service",
                "com.arvato.controller"
        })
@EnableAsync
@MapperScan(basePackages = "com.arvato.mapper.config")
public class WebFluxApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebFluxApplication.class, args);
    }
}


@RestController
@RequestMapping("/wxwork/sync")
public class WxworkSyncController {

	@Autowired
	private  WxworkSyncService wxworkSyncService;

	@GetMapping
	public Mono<String> sync() {
		// 異步處理業務
		wxworkSyncService.sync();
		return Mono.just("直接返回處理成功");
	}
	
}

@Service
public class WxworkSyncService {
	@Async
	public void sync() {
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(System.currentTimeMillis() + "--" + Thread.currentThread().getName());
	}
}

然後瘋狂發請求測試異步情況,並且打印線程名。我們發現默認情況下,每一次調用都是開啓一個新的線程,截圖如下:

可以看出來,@Async用的是SimpleAsyncTaskExecutor線程池,但是如果沒有對SimpleAsyncTaskExecutor做策略配置的話,是不復用線程的,這是對服務器資源的浪費。 

2.自定義線程池

自定義線程池很簡單,只要實現AsyncConfigurer接口,並且重寫getAsyncExecutor方法。

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;

@Configuration
@EnableAsync(proxyTargetClass = true)
@Slf4j
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (ex, method, params) ->
                log.error("Unexpected error occurred invoking async method: " + method +
                        ", args: " + Arrays.toString(params), ex);
    }

    /**
     * 自定義異步線程池
     * @return executor
     */
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(1000);
        executor.setThreadNamePrefix("MyExecutor-");
        executor.setWaitForTasksToCompleteOnShutdown(false);
        // 設置拒絕策略
        executor.setRejectedExecutionHandler((r, e) -> {
            throw new RejectedExecutionException("Task " + r.toString() +
                    " rejected from " +
                    e.toString());
        });
        executor.initialize();
        return executor;
    }
}

再次發請求測試:

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