一:Runable实现多线程创建方式
public static void main(String[] args) throws Exception{
System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());
new Thread(() -> {
System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());
try{
Thread.sleep(5000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());
}).start();
Thread.sleep(2000);
System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());
}
二:Thread
因为异步任务的实现本质的由新线程来执行任务,所以通过线程池的也可以实现异步执行。写法同我们利用线程池开启多线程一样。但由于我们的目的不是执行多线程,而是异步执行任务,所以一般需要另外一个线程就够了。
因此区别于执行多线程任务的我们常用的newFixedThreadPool,在执行异步任务时,我们用newSingleThreadExecutor 来创建一个单个线程的线程池。
public static void main(String[] args) throws Exception{
System.out.println("主线程 =====> 开始 =====> " + System.currentTimeMillis());
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(()->{
System.out.println("异步线程 =====> 开始 =====> " + System.currentTimeMillis());
try{
Thread.sleep(5000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("异步线程 =====> 结束 =====> " + System.currentTimeMillis());
});
executorService.shutdown(); // 回收线程池
Thread.sleep(2000);
System.out.println("主线程 =====> 结束 =====> " + System.currentTimeMillis());
}
三:@Async注解
我们都知道,SpringBoot项目有一个的很重要的特点就是的注解化。如果你的项目是SpringBoot,那就又多了一种选择——@Async注解。
使用起来也非常简单,将要异步执行的代码封装成一个方法,然后用@Async注解该方法,然后在主方法中直接调用就行。
也可以自己配置下线程池
@Bean(name = "asyncTaskExecutor")
public Executor asyncTaskExecutor() {
logger.info("--------------start asyncTaskExecutor------------------------");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(50);
executor.setMaxPoolSize(200);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-task-");
executor.setKeepAliveSeconds(30);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
使用时直接加上注解:
@Async("asyncTaskExecutor")
public void deleteFile(List<String> fileIdList) {
if (fileIdList==null || fileIdList.size()<1){
return;
}
logger.info("---异步执行-文件删除,待删除文件{}个---",fileIdList.size());
fileIdList.forEach(s -> {
try {
fileService.deleteFileByFileId(s);
logger.info("文件{}删除完成",s);
}catch (Exception e){
logger.error("文件{}删除时异常",s,e);
}
});
}
也可以这样使用
@Autowired
@Qualifier("asyncTaskExecutor")
ThreadPoolTaskExecutor executor;
public static void main(String[] args) {
//开启 异步 多线程
executor.execute(() -> {
try {
//归档
reqArchiveSystemService.postToArchiveSystem(contract);
} catch (Exception e){
logger.error("归档失败,使用原因:{}",e);
}finally {
jedisUtil.incrCount("transfer:count");
}
});
}