java线程异步方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | 异步的八种实现方式: 线程异步 Thread/Runnable Future + Callable 异步框架 CompletableFuture Spring 注解 @Async Spring ApplicationEvent 事件 第三方异步框架,比如 Hutool 的 ThreadUtil Guava 异步 消息队列 1、线程异步 public class ThreadTest implements Runnable{ @Override public void run() { System. out .println(Thread.currentThread().getName()); } public static void main(String[] args) { ThreadTest threadTest = new ThreadTest(); new Thread(threadTest).start(); } } 当然,如果每次都创建一个 Thread 线程,频繁的创建、销毁,浪费系统资源,我们可以采用线程池:【Thread】线程池的 7 种创建方式及自定义线程池 2、Future 异步 public class FutureTest { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executor = Executors.newFixedThreadPool(1); Future<String> future = executor.submit(() -> { Thread.sleep(2000); return "this is future execute final result!!!" ; }); //这里需要返回值时会阻塞主线程 String result = future. get (); System. out .println(result); executor.shutdown(); } } Future的不足之处的包括以下几点: 无法被动接收异步任务的计算结果:虽然我们可以主动将异步任务提交给线程池中的线程来执行,但是待异步任务执行结束之后,主线程无法得到任务完成与否的通知,它需要通过 get 方法主动获取任务执行的结果。 Future件彼此孤立:有时某一个耗时很长的异步任务执行结束之后,你想利用它返回的结果再做进一步的运算,该运算也会是一个异步任务,两者之间的关系需要程序开发人员手动进行绑定赋予,Future并不能将其形成一个任务流(pipeline),每一个Future都是彼此之间都是孤立的,所以才有了后面的CompletableFuture,CompletableFuture就可以将多个Future串联起来形成任务流。 Futrue没有很好的错误处理机制:截止目前,如果某个异步任务在执行发的过程中发生了异常,调用者无法被动感知,必须通过捕获 get 方法的异常才知晓异步任务执行是否出现了错误,从而在做进一步的判断处理 3、CompletableFuture 关于 CompletableFuture 更多详情请看:【异步】Futurn、FutureTask、CompletionService、CompletableFuture public static void thenRunAsync() throws ExecutionException, InterruptedException { CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> { System. out .println(Thread.currentThread() + " cf1 do something...." ); return 1; }); CompletableFuture<Void> cf2 = cf1.thenRunAsync(() -> { System. out .println(Thread.currentThread() + " cf2 do something..." ); }); //等待任务1执行完成 System. out .println( "cf1结果->" + cf1. get ()); //等待任务2执行完成 System. out .println( "cf2结果->" + cf2. get ()); } 4、Spring 注解 @Async @Configuration public class ThreadPoolConfig { @Bean( "taskExecutor" ) public Executor taskExecutor() { //返回可用处理器的Java虚拟机的数量 12 int i = Runtime.getRuntime().availableProcessors(); System. out .println( "系统最大线程数 : " + i); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心线程池大小 executor.setCorePoolSize(16); //最大线程数 executor.setMaxPoolSize(20); //配置队列容量,默认值为Integer.MAX_VALUE executor.setQueueCapacity(99999); //活跃时间 executor.setKeepAliveSeconds(60); //线程名字前缀 executor.setThreadNamePrefix( "asyncServiceExecutor -" ); //设置此执行程序应该在关闭时阻止的最大秒数,以便在容器的其余部分继续关闭之前等待剩余的任务完成他们的执行 executor.setAwaitTerminationSeconds(60); //等待所有的任务结束后再关闭线程池 executor.setWaitForTasksToCompleteOnShutdown( true ); return executor; } } @Service @EnableAsync public class AsyncServiceImpl implements AsyncService { @Override @Async( "taskExecutor" ) public String sendSms() { System. out .println(Thread.currentThread().getName()); return null ; } @Override @Async( "taskExecutor" ) public String sendEmail() { System. out .println(Thread.currentThread().getName()); return null ; } } 在实际项目中, 使用 @Async 调用线程池,推荐等方式是是使用自定义线程池的模式,不推荐直接使用 @Async 直接实现异步 5、Spring ApplicationEvent 事件 Spring 中使用事件只需要以下的几个步骤: 定义事件,继承 ApplicationEvent 定义监听,要么实现 ApplicationListener 接口,要么在方法上添加 @EventListener 注解 定义发布事件接口,调用 ApplicationContext.publishEvent() 或者 ApplicationEventPublisher.publishEvent(); 业务调用发布事件 @Getter @Setter public class BaseEvent<T> extends ApplicationEvent { private T data; public BaseEvent(Object source) { super(source); } public BaseEvent(Object source, T data) { super(source); this .data = data; } } @Component public class BaseEventListener implements ApplicationListener<BaseEvent<UserVo>> { @Override @Async( "taskExecutor" ) public void onApplicationEvent(BaseEvent<UserVo> baseEvent) { UserVo eventData = baseEvent.getData(); // TODO 业务处理 } } @Autowired private ApplicationContext applicationContext; @GetMapping( "/pubEvent" ) public void pubEvent() { BaseEvent<UserVo> baseEvent = new BaseEvent<>( "event" , new UserVo()); applicationContext.publishEvent(baseEvent); } 6、Hutool 的 ThreadUtil public static void main(String[] args) { for ( int i = 0; i < 3; i++) { ThreadUtil.execAsync(() -> { ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current(); int number = threadLocalRandom.nextInt(20) + 1; System. out .println(number); }); log.info( "当前第:" + i + "个线程" ); } log.info( "task finish!" ); } 7、 Guava 异步 public static void test() { ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); final ListenableFuture<Integer> listenableFuture = executorService.submit(() -> { log.info( "callable execute..." ); TimeUnit.SECONDS.sleep(1); return 1; }); Futures.addCallback(listenableFuture, new FutureCallback<Integer>() { @Override public void onSuccess(@Nullable Integer integer) { System. out .println( "Get listenable future's result with callback " + integer); } @Override public void onFailure(Throwable throwable) { throwable.printStackTrace(); } }, Executors.newCachedThreadPool()); } 8、 消息队列 常用的消息队列:RabbitMq、RocketMq |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤