Java -- JUC high concurrency programming, interview must ask (Callable&Future interface)

6.1 Callable interface

At present, we have learned that there are two methods to create threads - one is to create a Thread class, and the other is to create threads by using Runnable. However, one of the missing features of Runnable is that when the Thread terminates (that is, when run () completes), we cannot make the Thread return results. In order to support this function, the Callable interface is provided in Java.

Now we are learning the third scheme for creating threads - the Callable interface.
The characteristics of Callable interface are as follows (key points):

  • In order to implement Runnable, you need to implement the run () method that does not return anything, while for Callable, you need to implement the call () method that returns the result on completion.
  • The call () method can throw exceptions, while run () cannot.
  • The call method must be overridden to implement Callable
  • runnable cannot be replaced directly because the constructor of Thread class does not have Callable at all
Create a new class MyThread realization runnable Interface
class MyThread implements Runnable{
   @Override
   public void run() {
   }
}
New class MyThread2 realization callable Interface
class MyThread2 implements Callable<Integer>{
   @Override
   public Integer call() throws Exception {
      return 200;
   }
}

6.2 Future interface

When the call () method completes, the result must be stored in an object known to the main thread so that the main thread can know the result returned by the thread. To do this, you can use the Future object.

Think of future as an object that saves results – it may not save results temporarily, but it will be saved in the future (once Callable returns). Future is basically a way for the main thread to track progress and the results of other threads. To implement this interface, five methods must be rewritten. Important methods are listed here as follows:

  • public boolean cancel (boolean mayInterrupt): used to stop tasks. If not already started, it stops the task. If started, the task is interrupted only if mayInterrupt is true.
  • public Object get() throws InterruptedException ExecutionException: used to get the result of the task.
    If the task is completed, it will return the result immediately, otherwise it will wait for the task to complete and then return the result.
  • public boolean isDone(): if the task is completed, it returns true, otherwise it returns false. You can see that Callable and future do two things - Callable is similar to Runnable because it encapsulates the task to be run on another thread, and future is used to store the results obtained from another thread. In fact, future can also be used with Runnable.
    To create a thread, you need Runnable. In order to get results, we need future.

6.3 FutureTask

The Java library has a specific FutureTask type, which implements Runnable and Future, and conveniently combines the two functions. FutureTask can be created by providing Callable for its constructor. Then, the FutureTask object is supplied to the Thread constructor to create the Thread object. Therefore, Callable is used indirectly to create threads.

Core principles: (key points)
When time-consuming operations need to be performed in the main thread, but you don't want to block the main thread, you can hand over these jobs to the Future object to complete in the background.

  • When the main thread needs it in the Future, it can obtain the calculation results or execution status of the background job through the Future object • generally, FutureTask is mostly used for time-consuming calculation. The main thread can obtain the results after completing its own task.
  • The results can be retrieved only when the calculation is completed; Block the get method if the calculation is not yet complete
  • Once the calculation is completed, you cannot restart or cancel the calculation
  • get method, and the result can only be obtained when the calculation is completed. Otherwise, it will be blocked until the task turns to the completion state, and then the result will be returned or an exception will be thrown
  • Get is evaluated only once, so the get method is placed last

6.4 using Callable and Future

CallableDemo case

/**
* CallableDemo Case list
*/
public class CallableDemo {
 /**
 * Implement runnable interface
 */
 static class MyThread1 implements Runnable{
 /**
 * run method
 */
     @Override
     public void run() {
       try { System.out.println(Thread.currentThread().getName() + "Thread entered run method");
       }catch (Exception e){
         e.printStackTrace();
       }
     }
 }
 /**
 * Implement the callable interface
 */
 static class MyThread2 implements Callable{
 /**
 * call method
 * @return
 * @throws Exception
 */
      @Override
      public Long call() throws Exception {
        try {
          System.out.println(Thread.currentThread().getName() + "Thread entered call method,Start getting ready for bed");
          Thread.sleep(1000);
          System.out.println(Thread.currentThread().getName() + "I wake up");
       }catch (Exception e){
           e.printStackTrace();
      } return System.currentTimeMillis();
     }
 }
       public static void main(String[] args) throws Exception{
       //Declare runable
       Runnable runable = new MyThread1();
       //Declare callable
       Callable callable = new MyThread2();
       //future-callable
       FutureTask<Long> futureTask2 = new FutureTask(callable);
       //Thread two
       new Thread(futureTask2, "Thread two").start();
          for (int i = 0; i < 10; i++) {
              Long result1 = futureTask2.get();
              System.out.println(result1);
          }
       //Thread one
       new Thread(runable,"Thread one").start();
   }
}

6.5 summary (key points)

  • When the main thread needs to perform more time-consuming operations, but does not want to block the main thread, you can hand over these jobs to the Future object to complete in the background. When the main thread needs them in the Future, you can obtain the calculation results or execution status of the background job through the Future object • generally, FutureTask is mostly used for time-consuming calculations. After the main thread completes its own tasks, Then get the results
  • The results can be retrieved only when the calculation is completed; The get method is blocked if the calculation has not been completed. Once the calculation is completed, you cannot restart or cancel the calculation. Get method, and the result is obtained only when the calculation is completed. Otherwise, it will be blocked until the task turns to the completion state, and then the result will be returned or an exception will be thrown.
  • Calculate only once

Posted by cuongvt on Sun, 24 Oct 2021 04:16:18 -0700