一 future接口
1.1 future接口
future接口是jdk5之后提供的一个处理异步操作的接口,可以获取执行结果,取消执行结果,判断任务是否执行完成。
如果主线程需要执行一个耗时的计算任务,可以使用future把这个任务放到异步线程中执行。主线程继续处理其他任务或者先行结束,再通过future获取计算结果。
future接口可以为主线程开一个分支任务,专门为主线程处理耗时和费力的复杂业务。
特点:多线程,又返回值,异步任务。
缺点是:get方法是阻塞的;且获取之线程的状态是isDone方法需要写在while语句中,存在消耗cpu资源情况。
1.2 api
Runnable接口 无返回值;
callable接口 有返回值,且抛出异常;
future接口和futuretask接口。
目的异步多线程任务执行且有返回结果。例子老师让班长买水,为启动的异步多线程任务且买到水有结果返回。
1.3 代码
public class FutureDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
FutureTask<String> futureTask=new FutureTask<>(new MyTask());
Thread t= new Thread(futureTask,"t1");
t.start();
System.out.println("jieguo :"+futureTask.get());
}
}
线程类
public class MyTask implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println("callable come in....");
return "nihao";
}
}
1.4 场景案例
使用get,和isdone获取状态
package com.ljf.thread.future24;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* @ClassName: FutureGetStatus
* @Description: TODO
* @Author: admin
* @Date: 2024/03/19 16:54:37
* @Version: V1.0
**/
public class FutureGetStatus {
public static void main(String args[]) throws ExecutionException, InterruptedException {
System.out.println("");
FutureTask<Integer> task=new FutureTask(new Callable() {
@Override
public Object call() throws Exception {
Thread.sleep(3000);
int k=5;
return k;
}
});
Thread t1 = new Thread(task, "t1");
t1.start();
//主线程进行判断
while(true){
if(task.isDone()){
System.out.println("获取结果:"+task.get());
break;
}
else{
System.out.println("子线程还没有执行完。。。");
Thread.sleep(100);
}
}
}
}
二 CompletableFuture接口
2.1 创建任务
创建异步任务的方法: runAsync方法没有返回值;supplyAsync方法有返回值
public class CFBuild {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService= Executors.newFixedThreadPool(3);
CompletableFuture<Void> completableFuture=CompletableFuture.runAsync(new Runnable() {
@Override
public void run() {
System.out.println("没有返回值。。。。");
}
},executorService);
System.out.println(completableFuture.get());
CompletableFuture<String> completableFuture1=CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return "DDD";
}
},executorService);
System.out.println("c:"+completableFuture1.get());
executorService.shutdown();
}
}
2.2 回调任务
2.回调方法:如果我们需要对计算结果进行一个处理,它有一个计算完成时的回调方法,当CompletableFuture计算完成或者抛出异常的时候,whenCompleteAsync 用来处理正常的计算结果, exceptionally用来处理异常情况。
whenComplete:是执行当前任务的线程,继续执行whenComplete的任务。
whenCompleteAsync:是把执行whenCompleteAsync 这个任务继续提交给线程池来进行执行。方法不以Async结尾,意味着Action使用相同的线程执行;而以Async结尾,可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
public class CFWhenCompelete {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(3);
try {
CompletableFuture completableFuture= CompletableFuture.supplyAsync(new Supplier<Object>() {
public String get() {
return "DDD";
}
},threadPool).whenCompleteAsync((v,e)->{
if (e == null) {
System.out.println("-----计算完成,更新系统UpdateValue:"+v);
}
}).exceptionally((e)->{
e.printStackTrace();
System.out.println("异常情况:"+e.getCause()+"\t"+e.getMessage());
return null;
});
System.out.println(Thread.currentThread().getName()+"线程先去忙其它任务");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
threadPool.shutdown();
}
System.out.println("wo zai chazhao ");
}
}
2.3 获取结果join方法
当获取结果没有执行完,用填补值显示,执行完,返回执行结果。
System.out.println("jon2:"+ctf.complete("wancheng123")+" "+ctf.join());
package com.ljf.thread.future24;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
* @ClassName: CTFJoin
* @Description: TODO
* @Author: admin
* @Date: 2024/03/23 10:59:11
* @Version: V1.0
**/
public class CTFJoin {
public static void main(String args[]){
System.out.println("");
CompletableFuture<String> ctf=CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "over";
});
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
// System.out.println("join:"+ctf.join());
System.out.println("jon2:"+ctf.complete("wancheng123")+" "+ctf.join());
}
}
2.4 函数式接口
2.5 串行执行任务的方式
1.thenApply: 接收上游的值,自己处理结果,进行返回结果值。当前步骤错误,不往下游执行。
handler:有异常可以往下一步走。
2.thenAccept: 接收上游的值,自己处理结果,无返回值。
3.thenRun:不接收上游的值,自己处理结果,无返回值。
代码
public class CFBCuan {
public static void main(String[] args) {
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenRun(() -> {}).join());
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenAccept(r -> System.out.println(r)).join());
System.out.println(CompletableFuture.supplyAsync(() -> "resultA").thenApply(r -> r + "resultB").join());
}
}
结果
2.6 结果的选择与合并
1.使用applyToEither 选择其中一个。2.thenCombine 结果进行合并
public class CFBCombine {
public static void main(String[] args) throws InterruptedException {
CompletableFuture<String> cf1=CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "A";});
CompletableFuture<String> cf2=CompletableFuture.supplyAsync(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "B";});
// CompletableFuture<String> cf3= cf1.applyToEither(cf2,(f)->{ return f+"c";});
CompletableFuture<String> cf3= cf1.thenCombine(cf2,(a,b)->{ return a+b+"c";});
System.out.println("=-=======");
Thread.sleep(3000);
System.out.println("结果:"+cf3.join());
}
}
三 综合案例
3.1 案例异步查询数据
1.核心代码截图
2.完整代码
public class ListToMap {
public static void main(String[] args) {
Student stu=new Student();
stu.setName("ljf");
stu.setAge(23);
List<Student> list=new ArrayList<>();
list.add(stu);
Student stu2=new Student();
stu2.setName("beijing");
stu2.setAge(43);
list.add(stu2);
//list.stream().map((e)->{ return e.getName();}).forEach((x)->{System.out.println("x:"+x);});
// list.stream().map((e)->{ return "nihao:";}).collect(Collectors.toList());
// List<String> strList= list.stream().map(e -> "nihao:"+e.getName()).collect(Collectors.toList());
List<String> strList = show( list);
System.out.println("str:"+strList.toString());
List<String> strList2 = show2(list);
System.out.println("str2:"+strList2.toString());
}
public static List<String> show(List<Student> list){
return list.stream().map(e -> e.getName()+">>pinjie").collect(Collectors.toList());
}
public static List<String> show2(List<Student> list){
return list.stream().map(st -> CompletableFuture.supplyAsync(() -> String.format(st.getName() + " 的年龄是 is %d",
st.getAge()))).collect(Collectors.toList())
.stream()
.map(s -> s.join())
.collect(Collectors.toList());
}
}
3.执行结果