Several invocation methods:
Synchronized blocking call
It is called serially, and the response time is the sum of the response time of all services.
public class Test { public static void main(String[] args) throws Exception { RpcService rpcService = new RpcService(); HttpService httpService = new HttpService(); //Time consuming 10ms Map<String, String> result1 = rpcService.getRpcResult(); //Time consuming 20ms Integer result2 = httpService.getHttpResult(); //Total time consumed 30 ms } static class RpcService { Map<String, String> getRpcResult() throws Exception { //Calling remote methods (remote methods take about 10 ms and can be simulated using Thread.sleep) Thread.sleep(10); return null; } } static class HttpService { Integer getHttpResult() throws Exception { //Calling remote methods (remote methods take about 20 ms and can be simulated using Thread.sleep) Thread.sleep(20); return 0; } } }
Semi-asynchronous Future
Thread pool, asynchronous Future, usage scenario: concurrent requests for multiple services, the total response time is the longest; improve the total response time, but block the main request thread, high concurrency will still cause too many threads, CPU context switching;
Briefly speaking, Future mode can be described as follows: I have a task submitted to Future, and Future completes this task for me. In the meantime, I can do anything I want. After a while, I can get the results from Future.
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
public class Test { final static ExecutorService executor = Executors.newFixedThreadPool(2); public static void main(String[] args) { RpcService rpcService = new RpcService(); HttpService httpService = new HttpService(); Future<Map<String, String>> future1 = null; Future<Integer> future2 = null; try { //lambda expression writing Java 1.8 future1 = executor.submit(() -> rpcService.getRpcResult()); future2 = executor.submit(() -> httpService.getHttpResult()); //Other logical tasks can be performed here //It takes 10 ms, 300 is timeout time Map<String, String> result1 = future1.get(300, TimeUnit.MILLISECONDS); //Time consuming 20ms Integer result2 = future2.get(300, TimeUnit.MILLISECONDS); //Total time consumed 20ms } catch (Exception e) { if (future1 != null) { future1.cancel(true); } if (future2 != null) { future2.cancel(true); } throw new RuntimeException(e); } } static class RpcService { Map<String, String> getRpcResult() throws Exception { //Calling remote methods (remote methods take about 10 ms and can be simulated using Thread.sleep) } } static class HttpService { Integer getHttpResult() throws Exception { //Calling remote methods (remote methods take about 20 ms and can be simulated using Thread.sleep) } } }
Note: I strongly recommend that you read the java.util.concurrent-Java concurrent toolkit, where you will have time to organize a blog later.
Callback
Callback invocation, using scenarios: do not consider callback time and can only do simple processing of the results (written directly in the Future callback method), if the dependent service is two or more services, it can not merge the processing results of two services; do not block the main request thread, but use scenarios are limited.
Asynchronous callback chain arrangement
JDK8 Completable Future uses scenarios: Actually, it is not an asynchronous invocation, but a result orchestration of Callback invocation result processing, which relies on multiple services, to make up for the deficiency of Callback, so as to realize full asynchronous chain invocation. Here are some simple examples.
//Simulate one task to execute another public static void test() throws Exception { CompletableFuture<String> completableFuture1=CompletableFuture.supplyAsync(()->{ //Simulate time-consuming tasks System.out.println("task1 doing..."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Return result return "result1"; }); //After the first task is completed, the result of the task is passed to the parameter result, the later task is executed, and a completable Future representing the task is returned. CompletableFuture<String> completableFuture2= completableFuture1.thenCompose(result->CompletableFuture.supplyAsync(()->{ //Simulate time-consuming tasks System.out.println("task2 doing..."); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //Return result return "result2"; })); System.out.println(completableFuture2.get()); }