Learning note 06 of JUC high concurrency programming of Silicon Valley advanced technology -- Callable&Futrue interface

Keywords: JUC

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 has no Callable at all.

Comparison of thread creation between Runable interface and Callable interface

  • Whether there is a return value. The Callable interface has a return value, and the Runable interface has no return value.
  • Whether to trigger an exception. The Callable interface will throw an exception, and the Runable interface will not throw an exception.
  • The names of the implementation methods are different. The Callable interface implements the call() method and the Runable interface implements the run() method.

Find a class that is related to both Runable and Callable.

  • The Runable interface has an implementation class FutureTask.
  • FutureTask constructs can pass Callable.
//Create a new class MyThread to implement the runnable interface
class MyThread implements Runnable{
    @Override
    public void run() {
        
    }
}

//The new class MyThread2 implements the callable interface
class MyThread2 implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
    	return 200;
    }
}

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(): returns true if the task is completed; otherwise, returns false

    You can see that Callable and Future do two things -- Callable is similar to Runnable because it encapsulates tasks to run on another thread, and Future is used to store 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.

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 you need to perform time-consuming operations in the main thread, but do 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 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 has not yet completed.
  • 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 comes last.

Using Callable and Future

/**
 * 
 * Find a class that is related to both Runable and Callable
 *
 *   Runable Interface has implementation class FutureTask
 *
 *   FutureTask Construct Callable
 * 
 */


//Implement Runnable interface
class MyThread01 implements Runnable{

    @Override
    public void run() {

    }
}

//Implement Callable interface
class MyThread02 implements Callable {

    @Override
    public Integer call() throws Exception{
        System.out.println(Thread.currentThread().getName()+" come in callable");
        return 200;
    }
}

public class Demo01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //The Runnable interface creates a thread
        new Thread(new MyThread01(),"AA").start();

        //Callable interface creates a thread with an error
        //new Thread(new MyThread02()).start();

        //Provide Callable for constructor to create FutureTask
        FutureTask<Integer> futureTask1 = new FutureTask<>(new MyThread02());

        //lambda expressions 
        FutureTask<Integer> futureTask2 = new FutureTask<>(()->{
            System.out.println(Thread.currentThread().getName()+" come in callable");
            return 1024;
        });

        //Create a thread
        new Thread(futureTask1,"mary").start();
        new Thread(futureTask2,"lucy").start();

        /*while (!futureTask2.isDone()){
            System.out.println("wait...");
        }*/

        //Call the get method of FutureTask
        System.out.println(futureTask1.get());
        System.out.println(futureTask2.get());

        System.out.println(Thread.currentThread().getName()+ " come over");

        //FutureTask principle
        /**
         * 1. The teacher was thirsty in class and it was inappropriate to buy a ticket. The lecture thread continued. The single thread went to the monitor to buy water. After buying the water back, get it directly when necessary
         * 2. 4 Students: 1 student 1 + 2... + 5, 2 students 10 + 11 + 12... + 50, 3 students 60 + 61 + 62, 4 students 100 + 200
         *      The second student has a large amount of calculation
         *      FutureTask Open a single thread to 2 students for calculation. First summarize 1, 3 and 4. Finally, after 2 students complete the calculation, summarize them uniformly
         * 3. In the exam, first do the questions you can do, and finally look at the questions you can't do
         */
    }
}

summary

Posted by nmreddy on Fri, 19 Nov 2021 14:24:57 -0800