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:当执行被阻塞时使用的处理程序,因为线程边界和队列容量已经达到(当任务队列满了之后,按照指定的拒绝策略执行任务)

工作流程

  1. 线程池创建,准备好指定数量的核心线程数,准备接收任务
  2. 新的任务进来,用准备好的空闲线程执行。
  3. 核心线程满了,就将再进来的任务放入阻塞队列中。空闲的核心线程就会去阻塞队列获取任务执行。
  4. 阻塞队列满了,就直接开新线程执行,最大能开到maximumPoolSize指定的数量。
  5. maximumPoolSize都执行好了,maximumPoolSize数量空闲的线程会在keepAliveTime指定的时间后自动销毁,最终保存核心线程
  6. 如果线程数开到了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();
}
}
posted @   青橙e  阅读(583)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· 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
点击右上角即可分享
微信分享提示