Java线程池和异步任务
线程池的构造函数
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
构造函数的参数
int corePoolSize
:保留在池中的线程数,即使它们是空闲的,除非设置了允许核心线程超时(allowCoreThreadTimeOut)
int maximumPoolSize
:池中允许的最大线程数
long keepAliveTime
:当线程数大于核心线程数时,这是空闲线程在终止前等待新任务的最大时间。(空闲线程的存活时间)
TimeUnit unit
:keepAliveTime参数的时间单位
BlockingQueue<Runnable> workQueue
:用来存放核心线程来不及处理的任务,默认值为Integer的最大值。
ThreadFactory threadFactory
:执行程序创建新线程时使用的工厂
RejectedExecutionHandler handler
:当执行被阻塞时使用的处理程序,因为线程边界和队列容量已经达到(当任务队列满了之后,按照指定的拒绝策略执行任务)
工作流程
- 线程池创建,准备好指定数量的核心线程数,准备接收任务
- 新的任务进来,用准备好的空闲线程执行。
- 核心线程满了,就将再进来的任务放入阻塞队列中。空闲的核心线程就会去阻塞队列获取任务执行。
- 阻塞队列满了,就直接开新线程执行,最大能开到maximumPoolSize指定的数量。
- maximumPoolSize都执行好了,maximumPoolSize数量空闲的线程会在keepAliveTime指定的时间后自动销毁,最终保存核心线程
- 如果线程数开到了maximumPoolSize数量,还有新任务进来,就会使用handler指定的拒绝策略进行处理
常见的四种线程池
Executors.newCachedThreadPool()
带缓存的线程池,核心线程数为0,所有线程都可回收
使用的构造方法如下
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
Executors.newFixedThreadPool()
固定线程数的线程池,所有线程都不可回收
使用的构造方法如下
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
Executors.newScheduledThreadPool()
定时任务的线程池
Executors.newSingleThreadExecutor()
单线程的线程池,核心数是1,最大数也是1
使用的构造方法如下
CompletableFuture异步编排
CompletableFuture主要是用于异步调用,内部封装了线程池,可以将请求或者处理过程,进行异步处理。
CompletableFuture提供了四个静态方法来创建异步操作
//没有返回值 public static CompletableFuture<Void> runAsync(Runnable runnable) { return asyncRunStage(asyncPool, runnable); } //没有返回值,可指定线程池 public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) { return asyncRunStage(screenExecutor(executor), runnable); } //有返回值 public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) { return asyncSupplyStage(asyncPool, supplier); } //有返回值,可指定线程池 public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) { return asyncSupplyStage(screenExecutor(executor), supplier); }
开启异步任务
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务 CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> { int a = 1 + 1; return a; }, executorService); try { //获取返回结果 Integer result = completableFuture.get(); System.out.println("得到返回结果:" + result); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
任务完成回调和异常
whenComplete
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务 CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> { int a = 1 / 0; return a; }, executorService).whenComplete((res, exception) -> { System.out.println("异步任务完成,结果为:" + res); System.out.println("异常是:" + exception); }).exceptionally(throwable -> { //当发生异常时,返回默认值 return 0; }); try { Integer result = completableFuture.get(); System.out.println("结果为:" + result); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
handle
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务 CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> { int a = 1 / 0; return a; }, executorService).handle((res, exception) -> { if (res != null) { return res * 2; } if (exception!=null){ return 0; } return 0; }); try { Integer result = completableFuture.get(); System.out.println("结果为:" + result); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
线程串行化
thenRunAsync
:不能获取结果,没有返回值thenAcceptAsync
:可以获取结果,没有返回值thenApplyAsync
:可以获取结果,并且有返回值
thenRunAsync不能获取上一步的执行结果
例子
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务 CompletableFuture<Void> completableFuture = CompletableFuture.thenRunAsync(() -> { System.out.println("异步任务"); }, executorService).thenRunAsync(() -> { System.out.println("任务二启动"); }, executorService); }
thenAcceptAsync 可以获取上一步的结果,但是没有返回值
例子
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务 CompletableFuture.supplyAsync(() -> { System.out.println("异步任务"); int result = 1 + 1; return result; }, executorService).thenAcceptAsync(res -> { System.out.println("任务二启动,上一步的结果为:" + res); }, executorService); }
thenApplyAsync 可以获取上一步的结果,还有返回值
例子
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务 CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务"); int result = 1 + 1; return result; }, executorService).thenApplyAsync(res -> { System.out.println("任务二启动,上一步的结果为:" + res); return res * 2; }, executorService); try { Integer result = completableFuture.get(); System.out.println("结果是:" + result); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
两任务组合
当任务一和任务二都完成再执行任务三
runAfterBothAsync
:不能获取前两个任务的结果,也没有返回值thenAcceptBothAsync
:可以获取前两个任务的返回值,但是本身没有返回值thenCombineAsync
:可以获取前两个任务的结果,还能返回值
两个任务,只要有一个任务完成,就执行任务三
runAfterEitherAsync
:不能获取前一个任务的结果,也没有返回值acceptEitherAsync
:可以获取上一个任务的结果,但是没有返回值applyToEitherAsync
:可以获取上一步的返回结果,并且有返回值
runAfterBothAsync
runAfterBothAsync不能获取前两个任务的结果,也没有返回值
例子
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务1 CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务1结束"); return result; }, executorService); //开启异步任务2 CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务2结束"); return result; }, executorService); task.runAfterBothAsync(task2, () -> { System.out.println("任务3开始"); System.out.println("任务三结束"); }, executorService); }
thenAcceptBothAsync
可以获取前两个任务的返回值,但是本身没有返回值
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务1 CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务1结束"); return result; }, executorService); //开启异步任务2 CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务2结束"); return result; }, executorService); //任务组合 task.thenAcceptBothAsync(task2, (f1, f2) -> { System.out.println("执行任务3,当前线程是:" + Thread.currentThread().getId()); System.out.println("任务1返回值:" + f1); System.out.println("任务2返回值:" + f2); }, executorService); }
thenCombineAsync
可以获取前两个任务的结果,还能返回值
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务1 CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务1结束"); return result; }, executorService); //开启异步任务2 CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务2结束"); return result; }, executorService); //任务组合 CompletableFuture<Integer> task3 = task.thenCombineAsync(task2, (f1, f2) -> { System.out.println("执行任务3,当前线程是:" + Thread.currentThread().getId()); System.out.println("任务1返回值:" + f1); System.out.println("任务2返回值:" + f2); return f1 + f2; }, executorService); try { Integer res = task3.get(); System.out.println("最终结果:" + res); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
runAfterEitherAsync
不能获取前一个任务的结果,也没有返回值
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务1 CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务1结束"); return result; }, executorService); //开启异步任务2 CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务2结束"); return result; }, executorService); //任务组合 task.runAfterEitherAsync(task2, () -> { System.out.println("执行任务3,当前线程是:" + Thread.currentThread().getId()); }, executorService);
acceptEitherAsync
可以获取上一个任务的结果,但是没有返回值
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务1 CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务1结束"); return result; }, executorService); //开启异步任务2 CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 2; try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步任务2结束"); return result; }, executorService); //任务组合 task.acceptEitherAsync(task2, (res) -> { System.out.println("执行任务3,当前线程是:" + Thread.currentThread().getId()); System.out.println("上一个任务的结果为:"+res); }, executorService); }
applyToEitherAsync
可以获取上一步的返回结果,并且有返回值
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务1 CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务1结束"); return result; }, executorService); //开启异步任务2 CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 2; try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步任务2结束"); return result; }, executorService); //任务组合 CompletableFuture<Integer> task3 = task.applyToEitherAsync(task2, (res) -> { System.out.println("执行任务3,当前线程是:" + Thread.currentThread().getId()); System.out.println("上一个任务的结果为:" + res); return res * 3; }, executorService); try { Integer res = task3.get(); System.out.println("最终结果:" + res); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
多任务组合
allOf
:等待所有任务完成anyOf
:只要有一个任务完成
allOf
等待所有任务完成
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务1 CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务1结束"); return result; }, executorService); //开启异步任务2 CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 2; try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步任务2结束"); return result; }, executorService); //开启异步任务3 CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务3,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 3; try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步任务3结束"); return result; }, executorService); //任务组合 CompletableFuture<Void> allOf = CompletableFuture.allOf(task, task2, task3); try { //等待所有任务完成 allOf.get(); //获取任务的返回结果 System.out.println("task结果为:" + task.get()); System.out.println("task2结果为:" + task2.get()); System.out.println("task3结果为:" + task3.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
anyOf
只要有一个任务完成
public static void main(String[] args) { //创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); //开启异步任务1 CompletableFuture<Integer> task = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务1,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 1; System.out.println("异步任务1结束"); return result; }, executorService); //开启异步任务2 CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务2,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 2; try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步任务2结束"); return result; }, executorService); //开启异步任务3 CompletableFuture<Integer> task3 = CompletableFuture.supplyAsync(() -> { System.out.println("异步任务3,当前线程是:" + Thread.currentThread().getId()); int result = 1 + 3; try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("异步任务3结束"); return result; }, executorService); //任务组合 CompletableFuture<Object> anyOf = CompletableFuture.anyOf(task, task2, task3); try { //只要有一个有任务完成 Object o = anyOf.get(); System.out.println("完成的任务的结果:" + o); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix