Java开启异步的两种方式

打印 上一主题 下一主题

主题 843|帖子 843|积分 2529

二、Java开启异步的两种方式

1、注解开启:@Async

1.1、配置异步的线程池


  • 必须配置异步线程池,否则异步不会生效。
  • @EnableAsync 注解:指定异步线程池。不指定默认使用:SimpleAsyncTaskExecutor线程池
  • SimpleAsyncTaskExecutor是一个最简单的线程池,它没有任何的线程相关参数配置,它会为每个任务创建一个新的线程来执行,因此不建议在生产环境中使用。
  • 配置线程池见:https://www.cnblogs.com/kakarotto-chen/p/17428432.html
  1. package com.cc.md.config;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.scheduling.annotation.EnableAsync;
  5. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  6. import java.util.concurrent.ThreadPoolExecutor;
  7. /** IO型的线程池
  8. * @author CC
  9. * @since 2023/5/23 0023
  10. */
  11. @Configuration
  12. @EnableAsync
  13. public class IoThreadPool {
  14.     public static final int THREAD_SIZE = 2 * (Runtime.getRuntime().availableProcessors());
  15.    
  16.     public static final int QUEUE_SIZE = 1000;
  17.     @Bean(name = "myIoThreadPool")
  18.     public ThreadPoolTaskExecutor threadPoolExecutor(){
  19.         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  20.         executor.setCorePoolSize(THREAD_SIZE);
  21.         executor.setMaxPoolSize(THREAD_SIZE);
  22.         executor.setQueueCapacity(QUEUE_SIZE);
  23.         executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
  24.         executor.setKeepAliveSeconds(60);
  25.         executor.setAllowCoreThreadTimeOut(true);
  26.         executor.setAwaitTerminationSeconds(300);
  27.         executor.setWaitForTasksToCompleteOnShutdown(true);
  28.         executor.setThreadNamePrefix("myIo-Th-Pool-");
  29.         executor.initialize();
  30.         return executor;
  31.     }
  32. }
复制代码
1.2、异步方法


  • 异步方法必须写在另一个类中,否则不生效
  • @Async可以打在类上、也可以打在方法上
  1.     1 @Async:类上,说明整个类中的方法都是异步。必须写我们自己配置的线程池 —— ("myIoThreadPool")
  2.     2 @Async:方法上,说明这个方法是异步。不用写我们自己配置的线程池
复制代码

  • 异步接口+实现类
接口
  1. package com.cc.md.service;
  2. /**
  3. * @author CC
  4. * @since 2023/5/24 0024
  5. */
  6. public interface IAsyncService {
  7.     /** 异步方法1
  8.      * @since 2023/5/24 0024
  9.      * @author CC
  10.      **/
  11.     void async1();
  12.     /** 异步方法2
  13.      * @since 2023/5/24 0024
  14.      * @author CC
  15.      **/
  16.     void async2();
  17. }
复制代码
实现类
  1. package com.cc.md.service.impl;
  2. import com.cc.md.service.IAsyncService;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.scheduling.annotation.Async;
  6. import org.springframework.stereotype.Service;
  7. /** 1 @Async:类上,说明整个类中的方法都是异步。必须写我们自己配置的线程池 —— ("myIoThreadPool")
  8. *  2 @Async:方法上,说明这个方法是异步。不用写我们自己配置的线程池
  9. * @author CC
  10. * @since 2023/5/24 0024
  11. */
  12. @Service
  13. @Async("myIoThreadPool")
  14. public class AsyncServiceImpl implements IAsyncService {
  15.     private static final Logger log = LoggerFactory.getLogger(AsyncServiceImpl.class);
  16.     //类上写了@Async,这里就可以不写了。
  17.     //可以不写 ("myIoThreadPool")。因为在IoThreadPool中开启了异步,说明异步用的就是我们配置的io线程池
  18.     //如果类上面打了 @Async ,这里必须写:("myIoThreadPool")
  19.     @Override
  20.     //@Async
  21.     public void async1(){
  22.         //模仿io流耗时
  23.         try {
  24.             Thread.sleep(5000);
  25.         } catch (InterruptedException e) {
  26.             throw new RuntimeException(e);
  27.         }
  28.         log.info("打印:{}", "异步方法1111!");
  29.     }
  30.     //@Async在类上面,说明这个方法也是异步方法。如果不打,无法开启异步。
  31.     @Override
  32.     public void async2(){
  33.         //模仿io流耗时
  34.         try {
  35.             Thread.sleep(5000);
  36.         } catch (InterruptedException e) {
  37.             throw new RuntimeException(e);
  38.         }
  39.         log.info("打印:{}", "异步方法2222!");
  40.     }
  41. }
复制代码
1.3、测试
  1.     @Resource
  2.     private IAsyncService asyncService;
  3.    
  4.     //开启异步1 —— @Async
  5.     @Test
  6.     public void test03() throws Exception {
  7.         log.info("打印:{}", "异步测试的-主方法1");
  8.         asyncService.async1();
  9.         asyncService.async2();
  10.         //不会等待异步方法执行,直接返回前端数据
  11.         log.info("打印:{}", "异步测试的-主方法2");
  12.     }
复制代码
结果:

2、CompletableFuture的方式

使用:
  1.     @Resource(name = "myIoThreadPool")
  2.     private ThreadPoolTaskExecutor myIoThreadPool;
  3.    
  4.     //开启异步2 —— CompletableFuture.runAsync()
  5.     @Test
  6.     public void test04() throws Exception {
  7.         log.info("打印:{}", "异步测试的-主方法1");
  8.         CompletableFuture.runAsync(() -> {
  9.             log.info("打印:{}", "异步方法1!");
  10.             //异步执行的代码,也可以是方法,该方法不用单独写到其他类中。
  11.             this.async2("异步方法1!-end");
  12.         }, myIoThreadPool);
  13.         //不会等待异步方法执行,直接返回前端数据
  14.         log.info("打印:{}", "异步测试的-主方法2");
  15.     }
  16.     //异步需要执行的方法,可以写在同一个类中。
  17.     private void async2(String msg) {
  18.         //模仿io流耗时
  19.         try {
  20.             Thread.sleep(5000);
  21.         } catch (InterruptedException e) {
  22.             throw new RuntimeException(e);
  23.         }
  24.         log.info("打印:{}", msg);
  25.     }
复制代码
结果:


  • 后续CompletableFuture的使用见:《Java的CompletableFuture,Java的多线程开发》

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

灌篮少年

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表