多线程异步

文章详细介绍了Java线程池的基本概念,包括核心线程数、最大线程数、阻塞队列和拒绝策略等参数,并通过实例解析了线程池如何处理任务。此外,还讲解了CompletableFuture的使用,包括异步任务的创建、完成时的回调方法以及线程串行化操作,展示了如何在Java中实现高效的异步编程。
摘要由CSDN通过智能技术生成

一、知识点

1、线程池

线程池可以使用系统已有的线程池,也可以自己创建一个

1. 线程池7大参数

corePoolSize:核心线程数大小
maximumPoolSize:最大线程数
long keepAliveTime:非核心线程存活时间
TimeUnit unit:时间单位
BlockingQueue workQueue:阻塞队列
ThreadFactory threadFactory:线程创建工厂
RejectedExecutionHandler handler:拒绝策略

拒绝策略:

主要看juc包下的拒绝策略,juc包下系统提供的拒绝策略有4种:

AbortPolicy:抛弃任务,并抛出异常
CallerRunsPolicy:不进行异步执行,由任务的当前方法直接执行
DiscardOldestPolicy:抛弃最老的任务
DiscardPolicy:抛弃任务,不跑出异常

2、工作顺序

1、创建线程池,线程池准备核心线程,准备接收任务
2、如果核心线程满了,则将任务放到阻塞队列中
3、如果阻塞队列满了,则开启新线程,知道到达最大线程数
4、如果已经到达最大线程数据,则根据拒绝策略处理线程

举例:
创建了一个core:13,maxiMumPoolSize:20,workQueue:50的线程池,那么100个任务进来,处理顺序如下:

首先核心线程先获取13个任务,然后50个任务进入阻塞队列,再开7个非核心线程,剩下30个任务根据拒绝策略进行处理

3、系统提供的默认线程池

  1. Exectors.newCachedThreadPool():核心线程数是0,代表所有线程都会被回收
  2. Exectors.newFixedThreadPool():核心线程数=最大线程数,所有线程都不会被回收
  3. Exectors.newScheduledThreadPool():可以设置任务多久之后执行,用来做定时任务
  4. Exectors.newSingledThreadExectors()

为什么要使用线程池

1、降低损耗,通过重复利用已经创建好的线程,来降低创建和销毁线程的损耗
2、提高响应速度,当线程池中的线程数没有达到最大线程数时,有的线程处于等待任务的状态,因此有任务进来,能够立马被响应
3、利于管理线程,有助于管理线程的创建和销毁

2、线程异步编排

CompletableFuture

1. 创建异步对象

CompletableFuture由四种方法来执行异步任务

1. static void CompletableFuture.runAsync(Runnable runnable);

执行一个异步任务,不指定线程池,没有返回对象

2. static void CompletableFuture.runAsync(Runnable runnable,Exector exector);

执行一个异步任务,指定线程池,没有返回对象

3. static CompletableFuture.supplyAsync(Supplier supplier);

执行一个异步任务,不指定线程池,有返回对象

4. static CompletableFuture.supplyAsync(Supplier supplier,Exector exector);

执行一个异步任务,指定线程池,有返回对象

案例
ExectorService exector = Exectors.newFixedThreadPool();

CompletableFuture.runAsync(()->{
	//异步任务
});

CompletableFuture.runAsync(()->{
	//异步任务
},exector);

CompletableFuture<T> future = CompletableFuture.supplyAsync(()->{
	//异步任务
	return T
});

CompletableFuture<T> future = CompletableFuture.supplyAsync(()->{
	//异步任务
	return T;
},exector);
//通过future.get()获取返回结果
future.get()
2. 计算完成时回调方法
1.方法完成后的感知(无法处理返回结果)
1、public CompletableFuture whenComplete(BiConsumer<? supplier T,? supplier Throwable> action);

当任务完成时,利用该任务的线程执行action任务

2、public CompletableFuture whenCompleteAsync(BiConsumer<? supplier T,? supplier Throwable> action);

当任务完成时,重新开一个线程执行action任务

3、public CompletableFuture whenCompleteAsync(BiConsumer<? supplier T,? supplier Throwable> action,Exector exector);

当任务完成时,在指定线程池中重新开一个线程执行action任务

4、public CompletableFuture exceptionally(Function<Throwable,? extends T> fn);

如果任务出现异常,则使用fn函数处理

案例
future.whenComplete((res,exection)->{
	//res是返回的结果,exection是异常
});

future.whenCompleteAsync((res,exection)->{
	//res是返回的结果,exection是异常
});

future.whenCompleteAsync((res,exection,exector)->{
	//res是返回的结果,exection是异常,使用exector中的线程执行任务
});

future.execptionally(throwable -> {
	//感知异常,同时返回默认值
	return ...);
});
2.方法完成后的处理
1、public CompletionStage handle(BiFunction<? supper T,Throwable,? extends U> fn);

对返回结果进行处理,可捕获异常,使用当前任务的线程

2、public CompletionStage handleAsync(BiFunction<? supper T,Throwable,? extends U> fn);

对返回结果进行处理,可捕获异常,新开一个线程处理

3、public CompletionStage handleAsync(BiFunction<? supper T,Throwable,? extends U> fn,Exector exector);

对返回结果进行处理,可捕获异常,使用线程池中的线程处理

案例
future.handle((res,thr)->{
	//res是返回结果,thr是异常
})
//另外两个类似
3. 线程串行化

在这里插入图片描述

1、thenRun

任务完成之后,继续执行action,不感应返回结果,async表示开启异步线程

2、thenAccept

任务完成之后,action能够感知结果,然后执行action

3、thenApply

任务完成之后,action能够感知结果,执行action,并返回结果

其他方法见api(多任务组合)
CompletableFutureAPI

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值