在学习过程中碰到了这么个1.8的新特性,在此记录一下:
为了提高代码的执行效率,部分代码可以利用并发异步编程,达到优化的效果。
下面的可以说所有的方法都使用了线程池的方法进行测试,也可以使用直接利用lambda表达式直接写任务代码。都阔以。并且每个部分的具体解释,都在代码中有提现。
一、CompletableFuture有两个比较常用的方法:
package com.brave;
import java.util.concurrent.*;
public class CompletableFuture01 {
public static void main(String[] args) {
//创建一个线程池,用来执行线程任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
10,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
//利用completableFuture进行并发异步编程
/**
* runAsync 这个方法,没有返回值 ,那么CompletableFuture的泛型中就只能写Void
*/
CompletableFuture future1 = CompletableFuture.runAsync(()->{
System.out.println("任务1 : " + Thread.currentThread().getName());
},executor);
/**
* supplyAsync 这个方法,有返回值 ,那么CompletableFuture的泛型中可以写任意可返回的对象类型
* 这里用Object代替所有的类型
*/
CompletableFuture
二、如果线程执行完成需要对返回结果以及可能会发生的异常做处理,可以用whenCompleteAsync和exceptionally进行处理
package com.brave;
import java.util.concurrent.*;
public class CompletableFuture02 {
public static void main(String[] args) {
//创建一个线程池,用来执行线程任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
10,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
//利用completableFuture进行并发异步编程
/**
* whenCompleteAsync可以接收前面线程的返回值以及异常,可以进行返回值的逻辑
* 但是不能处理异常,并且没有返回值
* exceptionally 可以接收异常并处理异常,有返回值,返回值类型与前面线程的返回值类型相同
*/
CompletableFuture future1 = CompletableFuture.runAsync(()->{
System.out.println("任务1 : " + Thread.currentThread().getName());
},executor).whenCompleteAsync((result,exception)->{
System.out.println("whenCompleteAsync1接收返回值和异常信息");
System.out.println("result = " + result);
System.out.println("exception = " + exception);
},executor).exceptionally((exception) -> {
System.out.println("exceptionally1处理异常");
System.out.println(exception);
return null;
});
/**
* whenCompleteAsync可以接收前面线程的返回值以及异常,可以进行返回值的逻辑
* 但是不能处理异常,并且没有返回值
* exceptionally 可以接收异常并处理异常,有返回值,
* 返回值类型与前面线程的返回值类型相同,前线程没有返回值,那么就返回null
*/
CompletableFuture future2 = CompletableFuture.supplyAsync(()->{
System.out.println("任务2 : " + Thread.currentThread().getName());
return 100;
},executor).whenCompleteAsync((result,exception)->{
System.out.println("whenCompleteAsync1接收返回值和异常信息");
System.out.println("result = " + result);
System.out.println("exception = " + exception);
},executor).exceptionally((exception) -> {
System.out.println("exceptionally2处理异常");
System.out.println(exception);
return 100;
});
}
}
三、针对对返回结果以及可能会发生的异常做处理,除了用上面两个方法,还可以用handleAsync来代替上面两个方法:
package com.brave;
import java.util.concurrent.*;
public class CompletableFuture03 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建一个线程池,用来执行线程任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
10,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
System.out.println("========主线程开始=========" + Thread.currentThread().getName());
//利用completableFuture进行并发异步编程
/**
* handleAsync 可以说是替代了whenCompleteAsync和exceptionally
* 相当于他们两个结合起来
* 可以处理异常并拥有返回值
*/
CompletableFuture future1 = CompletableFuture.runAsync(()->{
System.out.println("任务1 : " + Thread.currentThread().getName());
},executor).handleAsync((result,exception)->{
System.out.println("result = " + result);
System.out.println("exception = " + exception);
return null;
},executor);
/**
* handleAsync 可以说是替代了whenCompleteAsync和exceptionally
* 相当于他们两个结合起来
* 可以处理异常并拥有返回值
*/
CompletableFuture future2 = CompletableFuture.supplyAsync(()->{
System.out.println("任务2 : " + Thread.currentThread().getName());
return 100;
},executor).handleAsync((result,exception)->{
System.out.println("result = " + result);
System.out.println("exception = " + exception);
return result + 10;
},executor);
System.out.println("future2.get() = " + future2.get());
System.out.println("=======主线程结束=========" + Thread.currentThread().getName());
}
}
四、如果想要多个线程按照顺序执行,那么就使用thenRunAsync,thenAcceptAsync, thenApplyAsync这三个方法:
package com.brave;
import java.util.concurrent.*;
public class CompletableFuture04 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建一个线程池,用来执行线程任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
10,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
System.out.println("========主线程开始=========" + Thread.currentThread().getName());
//利用completableFuture进行并发异步编程
//线程串行编程 最终的接收泛型要看最终的那个方法有没有返回值
/**
* thenRunAsync 在前面线程完成之后执行的线程,没有返回值,没有参数
* 可以让线程按顺序执行,因为不能接收前线程的返回值,所以在runAsync后面使用
*/
CompletableFuture future1 = CompletableFuture.runAsync(()->{
System.out.println("任务1 : " + Thread.currentThread().getName());
},executor).thenRunAsync(()->{
System.out.println("任务1-1 : " + Thread.currentThread().getName());
},executor);
/**
* thenAcceptAsync 可以接收前面线程的返回值,但是本身没有返回值
* 可以让线程按顺序执行 因为能接收前线程的返回值,所以在supplyAsync后面使用
*/
CompletableFuture future2 = CompletableFuture.supplyAsync(()->{
System.out.println("任务2 : " + Thread.currentThread().getName());
return 100;
},executor).thenAcceptAsync((result)->{
System.out.println("result = " + result);
},executor);
/**
* thenApplyAsync 可以接收前面线程的返回值,并且本身有返回值
* 可以让线程按顺序执行 因为能接收前线程的返回值,所以在supplyAsync后面使用
*/
CompletableFuture future3 = CompletableFuture.supplyAsync(() -> {
System.out.println("任务3 : " + Thread.currentThread().getName());
return 100;
}, executor).thenApplyAsync((result) -> {
System.out.println("result = " + result);
return result + 100;
}, executor);
System.out.println("=======主线程结束=========" + Thread.currentThread().getName());
}
}
五、线程编排,如果想要在两个任务完成之后才能进行第三个任务,那么就是用runAfterBothAsync,thenAcceptBothAsync,thenCombinAsync这三个方法:
package com.brave;
import java.util.concurrent.*;
public class CompletableFuture05 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建一个线程池,用来执行线程任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
10,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
System.out.println("========主线程开始=========" + Thread.currentThread().getName());
//利用completableFuture进行并发异步编程
//线程编排运行 两个任务都完成之后才进行第三个任务
CompletableFuture future1 = CompletableFuture.supplyAsync(()->{
System.out.println("任务1 : " + Thread.currentThread().getName());
return 20;
},executor);
CompletableFuture future2 = CompletableFuture.supplyAsync(()->{
System.out.println("任务2 : " + Thread.currentThread().getName());
return 100;
},executor);
/**
* 不能接收前两个线程的返回值,本身也没有返回值
*/
future1.runAfterBothAsync(future2,()->{
System.out.println("任务3 : " + Thread.currentThread().getName());
},executor);
/**
* 可以接收前两个线程的返回值,本身也没有返回值
*/
future1.thenAcceptBothAsync(future2,(f1,f2)->{
System.out.println("任务4 : " + Thread.currentThread().getName());
},executor);
/**
* 可以接收前两个线程的返回值,本身有返回值
*/
future1.thenCombineAsync(future2,(f1,f2)->{
System.out.println("任务4 : " + Thread.currentThread().getName());
return f1 + f2;
},executor);
System.out.println("=======主线程结束=========" + Thread.currentThread().getName());
}
}
六、线程编排,如果想要两个任务中,只要完成其中一个,就开始第三个任务,那么就用runAfterEitherAsync,acceptEitherAsync,applyToEitherAsync这三个方法:
package com.brave;
import java.util.concurrent.*;
public class CompletableFuture06 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建一个线程池,用来执行线程任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
10,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
System.out.println("========主线程开始=========" + Thread.currentThread().getName());
//利用completableFuture进行并发异步编程
//线程编排运行 两个线程任意完成一个就执行第三个线程
CompletableFuture future1 = CompletableFuture.supplyAsync(()->{
System.out.println("任务1 : " + Thread.currentThread().getName());
return 20;
},executor);
CompletableFuture future2 = CompletableFuture.supplyAsync(()->{
System.out.println("任务2 : " + Thread.currentThread().getName());
return 100;
},executor);
/**
* 不能接收前两个线程中完成的那个线程的返回值,本身也没有返回值
*/
future1.runAfterEitherAsync(future2,()->{
System.out.println("任务3 : " + Thread.currentThread().getName());
},executor);
/**
* 可以接收前两个线程中执行完成的那一个线程的返回值,本身没有返回值
*/
future1.acceptEitherAsync(future2,(result)->{
System.out.println("任务3 : " + Thread.currentThread().getName());
},executor);
/**
* 可以接收前两个线程中执行完成的那一个线程的返回值,本身有返回值
*/
future1.applyToEitherAsync(future2,(result)->{
System.out.println("任务4 : " + Thread.currentThread().getName());
return result + 100;
},executor);
System.out.println("=======主线程结束=========" + Thread.currentThread().getName());
}
}
七、多任务处理 ,多个任务想要一起运行就用allof,多任务运行只要其中一个任务执行完毕就进入主线程继续执行,剩下的线程仍然继续执行,那么就用anyof:
package com.brave;
import java.util.concurrent.*;
public class CompletableFuture07 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//创建一个线程池,用来执行线程任务
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5,
10,
10,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
System.out.println("========主线程开始=========" + Thread.currentThread().getName());
//利用completableFuture进行并发异步编程
//多任务处理 多个线程同时执行
CompletableFuture future1 = CompletableFuture.supplyAsync(()->{
System.out.println("任务1 : " + Thread.currentThread().getName());
return 20;
},executor);
CompletableFuture future2 = CompletableFuture.supplyAsync(()->{
System.out.println("任务2 : " + Thread.currentThread().getName());
return 100;
},executor);
/**
* 同时完成几个线程任务
*/
CompletableFuture f = CompletableFuture.allOf(future1, future2);
//阻塞方法:目的是等待所有线程执行完毕之后再回到主线程,
// 不然就会出现,线程开始了,不管有没有执行完,就回到了主线程
//f.get() 和 f.join() 都可以达到这个目的
f.get();
// f.join();
//future1.get() 这个方法可以获得任务的返回值
System.out.println("全部线程同时执行的" + future1.get() + "==" + future2.get());
/**
* anyof 是多任务中的任意一个完成之后,直接获取返回结果就可以
*/
CompletableFuture
这就是CompletableFuture!!!ending!