1、创建
/**
* public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier){..}
* public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor){..}
* public static CompletableFuture<Void> runAsync(Runnable runnable){..}
* public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor){..}
*
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void testCreateCompletableFuture() throws ExecutionException, InterruptedException {
// 方式一:
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() + " ===> 执行任务,有返回值");
return "qiu";
});
String result = future1.get();
System.out.println("result = " + result);
// 方式二:
ExecutorService pool = Executors.newFixedThreadPool(2);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() + " ===> 执行任务,有返回值,自定义线程池");
return "qiu";
}, pool);
result = future2.get();
System.out.println("future2 = " + future2);
// 方式三:
CompletableFuture<Void> future3 = CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName() + " ===> 执行任务,无返回值");
});
// 方式四:
CompletableFuture<Void> future4 = CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName() + " ===> 执行任务,有返回值,自定义线程池");
}, pool);
}
- supplyAsync :执行任务,支持返回值。
- runAsync:执行任务,没有返回值。
2、结果获取
/**
* //方式一
* public T get()
* //方式二
* public T get(long timeout, TimeUnit unit)
* //方式三
* public T getNow(T valueIfAbsent)
* //方式四
* public T join()
*/
@SneakyThrows
@Test
public void testGet(){
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("执行了一个任务");
return "qiu";
});
// getNow()
String futureNow = future.getNow("立刻获取");
System.out.println("futureNow = " + futureNow);
// get(time):超时抛出异常
// String r = future.get(10, TimeUnit.MICROSECONDS);
// System.out.println("r = " + r);
// get()
String result = future.get();
System.out.println("result = " + result);
// join()
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> System.out.println(1 / 0));
future1.join();
}
- get()和get(long timeout, TimeUnit unit) => 在Future中就已经提供了,后者提供超时处理,如果在指定时间内未获取结果将抛出超时异常
- getNow => 立即获取结果不阻塞,结果计算已完成将返回结果或计算过程中的异常,如果未计算完成将返回设定的valueIfAbsent值
- join => 方法里不会抛出异常
3、异步回调方法
thenRun()|thenRunAsync()
/**
无参无返回值 : 做完第一个任务后,再做第二个任务,第二个任务也没有返回值
* thenRun()
* thenRunAsync()
* @throws InterruptedException
*/
@Test
public void testUse() throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(1);
LocalDateTime startTime = LocalDateTime.now();
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + "第一个任务");
});
// thenRun()
CompletableFuture<Void> future1 = future.thenRun(() -> {
try {
Thread.sleep(400);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + "第二个任务");
});
// thenRunAsync()
future1.thenRunAsync(() -> {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + "第三个任务");
},pool);
Thread.sleep(1300);
LocalDateTime endTime = LocalDateTime.now();
Duration duration = Duration.between(startTime, endTime);
System.out.println("共耗: " + duration.toHours() + " 小时, " + duration.toMinutes() + " 分钟, "
+ duration.getSeconds() + " 秒, " + duration.toMillis() + " 毫秒");
}
如果你执行第一个任务的时候,传入了一个自定义线程池:
- 调用thenRun方法执行第二个任务时,则第二个任务和第一个任务是共用同一个线程池。
- 调用thenRunAsync执行第二个任务时,则第一个任务使用的是你自己传入的线程池,第二个任务使用的是ForkJoin线程池。
thenAccept()|thenAcceptAsync()
/**
* 有参无返回值:第一个任务执行完成后,执行第二个回调方法任务,会将该任务的执行结果,作为入参,传递到回调方法中,但是回调方法是没有返回值的。
* thenAccept(params)
* thenAcceptAsync(params)
*/
@Test
public void testAccept() throws ExecutionException, InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(2);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "qiu");
CompletableFuture<Void> accept = future.thenAccept((e) -> {
System.out.println("上一个任务的返回值 = " + e);
});
// 无返回值 null
System.out.println("accept.get() = " + accept.get());
CompletableFuture<Void> accept2 = future.thenAcceptAsync((e) -> {
System.out.println("上一个任务的返回值 = " + e);
});
System.out.println("accept2.get() = " + accept2.get());
}
thenApply()|thenApplyAsync()
/**
* 有参有返回值:表示第一个任务执行完成后,执行第二个回调方法任务,会将该任务的执行结果,作为入参,传递到回调方法中,并且回调方法是有返回值的
* thenApply()
* thenApplyAsync()
*/
@Test
public void testApply() throws ExecutionException, InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(2);
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "qiu");
CompletableFuture<String> future1 = future.thenApply((e) -> e);
System.out.println("上一个任务的返回值future = " + future1.get());
CompletableFuture<String> future2 = future1.thenApplyAsync((e) -> e, pool);
System.out.println("上一个任务的返回值future1 = " + future2.get());
}
4、异常回调
whenComplete:当CompletableFuture的任务不论是正常完成还是出现异常它都会调用「whenComplete」这个回调函数。
- 正常完成:whenComplete返回结果和上级任务一致,异常为null;
- 出现异常:whenComplete返回结果为null,异常为上级任务的异常;
即调用get()时,正常完成时就获取到结果,出现异常时就会抛出异常,需要你处理该异常
/**
* whenComplete:
*/
@Test
public void testWhenComplete() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (Math.random() < 0.5) {
throw new RuntimeException("出错了!!!");
}
System.out.println("正常结束");
return 11;
}).whenComplete((e, t) -> {
if (e == null) {
System.out.println("whenComplete e is null");
} else {
System.out.println("whenComplete e is " + e);
}
if (t == null) {
System.out.println("whenComplete t is null");
} else {
System.out.println("whenComplete t is " + t.getMessage());
}
});
System.out.println("结果 = " + future.get());
}
whenComplete + exceptionally exceptionally会捕获任务执行中的异常,然后给一个默认的返回值
@Test
public void testWhenComplete() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
if (Math.random() < 0.5) {
throw new RuntimeException("出错了!!!");
}
System.out.println("正常结束");
return 11;
}).whenComplete((e, t) -> {
if (e == null) {
System.out.println("whenComplete e is null");
} else {
System.out.println("whenComplete e is " + e);
}
if (t == null) {
System.out.println("whenComplete t is null");
} else {
System.out.println("whenComplete t is " + t.getMessage());
}
}).exceptionally(t -> {
System.out.println("出现异常了:" + t.getMessage());
return 0;
});
System.out.println("结果 = " + future.get());
}
结果:
whenComplete e is null
whenComplete t is java.lang.RuntimeException: 出错了!!!
出现异常了:java.lang.RuntimeException: 出错了!!!
结果 = 0
5、多任务组合之 AND
/**
* 多任务组合之 AND
* thenCombine / thenAcceptBoth / runAfterBoth都表示:「当任务一和任务二都完成再执行任务三」。
* 区别在于:
* runAfterBoth: 不会把执行结果当做方法入参,且没有返回值
* thenAcceptBoth: 会将两个任务的执行结果作为方法入参,传递到指定方法中,且无返回值
* thenCombine: 会将两个任务的执行结果作为方法入参,传递到指定方法中,且有返回值
*/
@Test
public void testAnd() throws ExecutionException, InterruptedException {
//创建线程池
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);
Integer res = task3.get();
System.out.println("最终结果:" + res);
}
6、多任务组合之 OR
/**
* 多任务组合之 OR
* applyToEither / acceptEither / runAfterEither 都表示:「两个任务,只要有一个任务完成,就执行任务三」。
* 区别在于:
* runAfterEither:不会把执行结果当做方法入参,且没有返回值
* acceptEither: 会将已经执行完成的任务,作为方法入参,传递到指定方法中,且无返回值
* applyToEither:会将已经执行完成的任务,作为方法入参,传递到指定方法中,且有返回值
*/
@Test
public void testOR() {
// 创建线程池
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);
}
7、多任务组合
allOf:等待所有任务完成
@Test
public void testallOf() throws ExecutionException, InterruptedException {
//创建线程池
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);
//等待所有任务完成
allOf.get();
//获取任务的返回结果
System.out.println("task结果为:" + task.get());
System.out.println("task2结果为:" + task2.get());
System.out.println("task3结果为:" + task3.get());
}
anyOf() : 只要有一个任务完成
@Test
public void testAnyOf() throws ExecutionException, InterruptedException {
//创建线程池
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> future = CompletableFuture.anyOf(task, task2, task3);
//某一人任务完成
Object res = future.get();
System.out.println("res = " + res);
//获取任务的返回结果
System.out.println("task结果为:" + task.get());
System.out.println("task2结果为:" + task2.get());
System.out.println("task3结果为:" + task3.get());
}
标签:异步,编程,System,任务,CompletableFuture,println,out
From: https://www.cnblogs.com/qbbit/p/16912929.html