前言:Futrue的缺點有(1)get方法會阻塞 ,(2)不支持注冊回調方法 ,(3)不支持級聯操作
CompletableFuture彌補了這些缺點
直接上代碼:
public class CompletableFutureTest {
public static void main(String[] args) throws Exception {
// test1();
// test2();
// test3();
test4();
}
//采用了callable+ future方式 ,get方法獲取任務的返回值會被阻塞住
public static void test1() throws Exception {
ExecutorService executor = Executors.newCachedThreadPool();
Future<String> result = executor.submit(()->{
//模擬執行耗時任務
System.out.println("task doing...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//返回結果
return "result";
});
//這里只是將空閑的線程中斷,將線程池的狀態改為shutdown,不能繼續往線程池中添加任務
executor.shutdown();
System.out.println("task運行結果" + result.get());
}
//采用了competableFuture,采用回調的方式獲取任務的返回值
public static void test2() throws Exception {
//supplyAsync內部使用ForkJoinPool線程池執行任務
CompletableFuture<String> completableFuture=CompletableFuture.supplyAsync(()->{
//模擬執行耗時任務
System.out.println("task doing...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//返回結果
return "100";
}).whenComplete((v,r)->{
System.out.println("計算結果是: "+v);
});
//CompletableFuture里使用的線程池里的線程默認是daemon的。main線程結束后,整個程序也
//結束了,這里將main線程join后任務里的代碼才可以執行完
Thread.currentThread().join();
}
//compeltableFuture可以支持級聯操作
public static void test3() throws Exception {
IntStream.range(1,10).boxed().forEach( i -> CompletableFuture.supplyAsync(CompletableFutureTest::get)
.thenAccept(CompletableFutureTest::display)
.whenComplete((v,r)->
System.out.println(i +" have done")
)
);
Thread.currentThread().join();
}
public static void display(int data){
int value = ThreadLocalRandom.current().nextInt(10);
try {
System.out.println(Thread.currentThread().getName() +" display data "+ data+" will sleep "+value);
TimeUnit.SECONDS.sleep(value);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +" dispaly have done with data = "+data);
}
public static int get(){
int value = ThreadLocalRandom.current().nextInt(10);
try {
System.out.println(Thread.currentThread().getName() +" get will sleep "+value);
TimeUnit.SECONDS.sleep(value);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +" get have done "+value);
return value;
}
//兩個線程分別執行任務,任務都執行完后再執行最后的runnable
public static void test4() throws InterruptedException {
CompletableFuture.supplyAsync(Object::new)
.thenAcceptAsync(obj -> {
try {
System.out.println("obj ====== start");
TimeUnit.SECONDS.sleep(5);
System.out.println("obj ====== " + obj);
} catch (InterruptedException e) {
e.printStackTrace();
}
}).runAfterBoth(CompletableFuture.supplyAsync(() -> "hello")
.thenAcceptAsync((v) -> {
try {
System.out.println("string ====== start");
TimeUnit.SECONDS.sleep(3);
System.out.println("string ====== " + v);
} catch (InterruptedException e) {
e.printStackTrace();
}
}), () -> System.out.println("finished"));
Thread.currentThread().join();
}
//一個線程計算奇數和,一個線程計算偶數和,main線程將他們相加
public static void test9() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> oddNumber = CompletableFuture.supplyAsync(()->{
try {
System.out.println("開始計算奇數和 ...");
Thread.sleep(3_000);
System.out.println("結束計算奇數和 ...");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 1+3+5+7+9;
});
CompletableFuture<Integer> evenNumber = CompletableFuture.supplyAsync(()->{
try {
System.out.println("開始計算偶數和 ...");
Thread.sleep(5_000);
System.out.println("結束計算偶數和 ...");
} catch (InterruptedException e) {
e.printStackTrace();
}
return 2+4+6+8;
});
long startTime = System.currentTimeMillis();
CompletableFuture<Integer> resultFuturn = oddNumber.thenCombine(evenNumber,(odd,even)->{
return odd + even;
});
System.out.println("===============");
System.out.println("運行結果是:"+resultFuturn.get()+" 總共耗時:"+ (System.currentTimeMillis()-startTime) +"毫秒");
}
}
