Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities.

preface

  • In some scenarios, unimportant tasks can be processed asynchronously, and in some cases, callback results of asynchronously executed tasks need to be retrieved
  • At this point, you can use the Future interface. This time, in combination with my personal understanding, I will document the advanced use of the Asynchronous callback of the Future interface for Future reference.

FutureTask

  • When a task is executed asynchronously using a thread pool, the submit() method is used to submit the task if you want to obtain the results of the execution.
  • It encapsulates a FutureTask and blocks the result with the get() method (pseudo-asynchronous) :
public static void main (String[] args) throws Exception { ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(4, 4, 30, TimeUnit.SECONDS, new LinkedBlockingQueue(6)); // Example: Future<? > submit = executor.submit (() -> {log.info("FutureTask used, no return value "); }); Log.info (" used by FutureTask, no return value: "+ submit. Get ()); Future<String> submit1 = executor.submit (() -> {log.info("FutureTask uses, returns value "); return "1"; }); Log.info (" used by FutureTask, return value: "+ submit1.get()); Num = new AtomicInteger(1); Future<AtomicInteger> submit2 = executor.submit (() -> {log.info("FutureTask uses, multiple parameters "); num.set(2); }, num); Log.info ("FutureTask use, multiple arguments: "+ submit2.get()); } ----------------------------- Print result: 18:07:17.346 - [pool-2-thread-1] -futureTask, no return value 18:07:17.348 - [main] -futureTask, no return value: Null 18:07:17.349 - [pool-2-thread-2] -futureTask, with return value 18:07:17.349 - [main] -futureTask, with return value: 1 18:07:17.350 - [pool-2-thread-3] -FutureTask with multiple parameters 18:07:17.350 - [main] -futureTask with multiple parameters: 2Copy the code
The FutureTask callback will block the main thread. If you want to stop blocking the main thread, you can use the following mechanismsCopy the code

ListenableFuture

  • Google’s Guava package provides a callback class that does not block the main thread, ListenableFuture, whose extended Future interface provides a method, addListener()
  • If you want to use the callback mechanism, you’ll need to decorate the custom thread pool ThreadPoolExecutor using the MoreExecutors object
  • Returns a ListenableFuture object after submitting a task using the Thread pool decorated by MoreExecutors
  • Call the addListener() method on the ListenableFuture object to register a listener object and thread pool. A listener is raised when a thread task completes execution:
public static void main (String[] args) throws Exception { ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(4, 4, 30, TimeUnit.SECONDS, new LinkedBlockingQueue(6)); Log.info (" Date goddess to see a movie "); ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EXECUTOR); ListenableFuture<String> Future = executorService.submit(() -> {log.info(" the Muse started to make up "); ListenableFuture<String> Future = executorService.submit(() -> {log.info(" the Muse started to make up "); try { Thread.sleep(3000); } catch (InterruptedException e) {} return "The goddess is finished "; }); Future.addlistener (() -> {try {log.info(" normal callback: "+ future.get())); } catch (InterruptedException e) { } catch (ExecutionException e) { } }, executorService); Log.info (" I'll do other things first "); Thread.currentThread().join(); } -------------------------- Print result: 18:08:23.975 - [main] - I do other things first 18:08:26.989 - [pool-2-thread-2] - Normal callback: Goddess makeup is finishedCopy the code

FutureCallback

  • You can use the FutureCallback object if you want to customize the control submitted to the thread pool for an exception
public static void main (String[] args) throws Exception { ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(4, 4, 30, TimeUnit.SECONDS, new LinkedBlockingQueue(6)); Log.info (" Date goddess to see a movie "); ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EXECUTOR); ListenableFuture<? Executorservice.submit (() -> {log.info(); try { Thread.sleep(3000); } catch (Exception e) {} // throw new RuntimeException(); Return "Goddess makeup is finished "; }); Futures.addCallback(future, New FutureCallback<Object>() {@override public void onSuccess (Object result) {log.info(" normal callback: "+ result); } @override public void onFailure (Throwable t) {log.info(" exception callback: "+ t.gettmessage ()); }}); Log.info (" I'll do other things first "); Thread.currentThread().join(); } ------------------------------- Print result: 18:12:25.903 - [main] - I do other things first 18:12:28.899 - [pool-2-thread-1] - Normal callback: Goddess makeup is finishedCopy the code
  • Opening the exception comment in the demo and executing the code results in the following:
18:13:26.373 - [main] - I'll do something else first 18:13:29.368 - [pool-2-thread-1] - Exception callback: Goddess is not wearing makeupCopy the code

CompletableFuture

  • CompletableFuture is a callback mechanism introduced after JDK 8, and FutureTask was released in JDK 1.5
  • CompletableFuture can be seen as an enhancement to the Future that does not block the main thread to get callback results (truly asynchronous)
  • Tasks are performed using the CompletableFuture object, which does not require a custom thread pool (an extension to the custom thread pool is provided internally) and uses the ForkJoinPool.commonPool() thread pool by default
  • In addition to not blocking the main thread to get callback results, you can also customize the handling of exception scenarios:
public static void main (String[] args) throws Exception { ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(4, 4, 30, TimeUnit.SECONDS, new LinkedBlockingQueue(6)); Log.info (" Date goddess to see a movie "); CompletableFuture. SupplyAsync (() - > {the info (" goddesses began to make up the "); try { Thread.sleep(3000); } catch (InterruptedException e) {} return "The goddess is finished "; // throw new RuntimeException(" No makeup "); }). WhenComplete ((result, throwable) -> {if (throwable == null) {log.info(" normal callback: "+ result); return; } log.info(" exception callback: "+ throwable.getMessage()); return; }); Log.info (" I'll do other things first "); Thread.currentThread().join(); } ------------------------------- Print result: 18:15:13.831 - [ForkJoinPool.com monpool-worker-1] - The goddess begins to put on makeup 18:15:13.832 - [main] - 18:15:16.833 - [ForkJoinPool.com monpool-worker-1] - Normal callback: Goddess makeup is doneCopy the code
  • Opening the exception comment in the demo and executing the code results in the following:
18:15:42.565 - [main] - Ask goddess to see a movie 18:15:42.600 - [ForkJoinPool.com monpool-worker-1] - Goddess begins to put on makeup 18:15:42.600 - [main] - I'll do other things 18:15:45. 601 -] [ForkJoinPool.com monPool - worker - 1 - abnormal callback: Java. Lang. RuntimeException: the goddess doesn't make upCopy the code
  • CompletableFuture provides many useful methods, and the demo illustrates two methods for submitting a task and executing a callback when the task is completed. Other methods readers can operate by themselves

The last

  • Learn with an open mind and make progress together