CompletableFuture
Four static methods
-
RunAsync (no return value)
-
public static CompletableFuture runAsync(Runnable runnable)
-
public static CompletableFuture runAsync(Runnable runnable, Executor executor)
-
-
SupplyAsync (return value)
-
public static CompletableFuture supplyAsync(Supplier supplier)
-
public static CompletableFuture supplyAsync(Supplier supplier, Executor executor)
-
The Executor Executor parameter, when not specified, defaults to ForkJoinPool.commonPool() as a thread pool to execute asynchronous code
Code examples:
ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 8, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); CompletableFuture. RunAsync (() - > {System. Out. Println (" don't specify a Thread pool parameter, the current Thread: "+ Thread. The currentThread (). The getName ()); }); CompletableFuture. RunAsync (() - > {System. Out. Println (" specified parameters of the Thread pool, the current Thread: "+ Thread. The currentThread (). The getName ()); }, executor); executor.shutdown();Copy the code
Output result:
If pool-1-thread-1 is specified, the current thread is ForkJoinPool.com monpool-worker-3Copy the code
Commonly used method
1. Get results and trigger calculations
Get results:
- Public T get() // block until the calculation is complete
- Public T join() // block until the calculation is complete
- Public T get(long timeout, TimeUnit Unit) // Wait for the specified time. If no result is obtained after the specified time, an exception is thrown
- Public T getNow(T valueIfAbsent) // Obtains the result immediately, calculates the return result, and does not calculate the return value valueIfAbsent
Code examples:
Integer result = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 123;
}).join();
System.out.println(result);
CompletableFuture<Integer> futureResult = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 123;
});
System.out.println(futureResult.get());
System.out.println(futureResult.getNow(456));
System.out.println(futureResult.get(2, TimeUnit.SECONDS));
Copy the code
Active trigger calculation:
- public boolean complete(T value)
Code examples:
public static void main(String[] args) throws InterruptedException, ExecutionException { CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } return 11; }); // When get() is blocked, the complete method ends the block and get() gets the value of the set complete system.out.println (future.complete(666)); // Print true system.out.println (future.get()); // output 666}Copy the code
2. Process the calculation results
- thenApply
- handle
When one thread depends on another, handle is used to serialize the two threads
public static void main(String[] args) throws InterruptedException {
CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(11);
return 11;
}).handle((r, e) -> {
System.out.println(22);
return r + 1;
}).handle((r, e) -> {
System.out.println(33);
return r + 1;
}).exceptionally(e -> {
e.printStackTrace();
return null;
});
TimeUnit.SECONDS.sleep(2);
}
Copy the code
3. Consume the calculated results
- thenRun
After task A is finished, execute task B, which does not need the result of A
CompletableFuture.runAsync(() -> {
System.out.println(Thread.currentThread().getName());
}).thenRun(() -> System.out.println("finish"));
Copy the code
- thenAccept
Task B needs the result of task A, but task B has no return value
CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName());
return 1;
}).thenAccept(System.out::println);
Copy the code
- thenApply
After task A is finished, execute task B, which needs the result of A and has A value returned by task B
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName());
return 1;
}).thenApply(a -> {
// 1
System.out.println(a);
return a + 1;
}).thenApply(b -> {
// 2
System.out.println(b);
return b + 2;
});
// 4
System.out.println(future.get());
Copy the code
4. Choose the speed of calculation (who uses quickly)
- applyToEither
Sample code:
CompletableFuture < Integer > future = CompletableFuture. SupplyAsync (() - > {System. Out. Println (" thread 1: "+ thread.currentThread ().getName() "); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } return 10; }). ApplyToEither (CompletableFuture supplyAsync (() - > {System. Out. Println (" thread 2: "+ thread.currentThread ().getName() "); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } return 20; }), f -> {system.out.println (" who calculates fast who "); return f + 1; }); System.out.println(future.get());Copy the code
Output result:
Thread 1:ForkJoinPool.com starting monPool - worker - 3 thread 2:ForkJoinPool.com starting monPool - worker - 5 Whoever computing fast with 11Copy the code
5. Combine the calculated results
- thenCombine
Usage scenario: Requests data from multiple interfaces and returns the data after merging
Sample code:
CompletableFuture < Integer > future = CompletableFuture. SupplyAsync (() - > {System. Out. Println (" thread 1: " + Thread.currentThread().getName()); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } return 10; }). ThenCombine (CompletableFuture supplyAsync (() - > {System. Out. Println (" Thread 2: "+ Thread. CurrentThread (). The getName ()); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } return 20; }), (a, b) -> {system.out.println (); return a + b; }); System.out.println(future.get());Copy the code
Output result:
Thread 1 forkJoinpool.com monpool-worker-3 Thread 2 Forkjoinpool.com monpool-worker-7 Merges the results 30Copy the code
The sample
Multi-platform commodity price comparison, two ways of execution time comparison
import java.util.List; import java.util.concurrent.*; import java.util.stream.Collectors; public class CompletableFutureNetMallDemo { static List<NetMall> list = List.of(new NetMall("jd"), new NetMall("pdd"), new NetMall("tmall"), new NetMall("taobao"), new NetMall("dangdang"), new NetMall("shop1"), new NetMall("shop2"), new NetMall("shop3"), new NetMall("shop4"), new NetMall("shop5")); public static void main(String[] args) { var start = System.currentTimeMillis(); var firstList = getPriceByStep(list, "Java"); for (String s : firstList) { System.out.println(s); + (system.currentTimemillis () -start) + "milliseconds "); var start1 = System.currentTimeMillis(); var secondList = getPriceAsync(list, "Java"); for (String s : secondList) { System.out.println(s); } system.out.println ("CompletableFuture asynchronous operation execution time: "+ (system.currentTimemillis () -start1) +" milliseconds "); } public static list <String> public static list <String> getPriceByStep(List<NetMall> list, String productName) { return list.stream() .map(netMall -> String.format(productName + " in %s price is %.2f", netMall.getMallName(), netMall.calcPrice(productName))) .collect(Collectors.toList()); } /** * CompletableFuture asynchronous operation ** @param list platform list * @param productName productName * @return calculation result */ public static List<String> getPriceAsync(List<NetMall> list, String productName) { return list.stream() .map(netMall -> CompletableFuture.supplyAsync(() -> String.format(productName + " in %s price is %.2f", netMall.getMallName(), netMall.calcPrice(productName)))) .collect(Collectors.toList()) .stream().map(CompletableFuture::join) .collect(Collectors.toList()); } } class NetMall { private final String mallName; public String getMallName() { return mallName; } public NetMall(String mallName) { this.mallName = mallName; } public double calcPrice(String productName) {// Return a random number return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0); }}Copy the code