Detailed explanation of multithreaded callable

Someone in the interview will ask: How many ways are there to implement threads?
Many people may answer: 2 types, inherit the Thread class and implement the Runnable interface.
Many ignore callable this way.
Maybe someone knows callable, and also knows that the difference between callable and Runnable is that callable can return a value or throw an exception, while Runnable does not.

It is estimated that many people are confused here, and then we will explain this issue from the source code level.

It is critical to note that callables can have return values, as well as throw exceptions.
Many times we let multi-threading help us deal with things, we need to get the return value, and it can also be handled if there is an exception. For example, on the APP page of a certain treasure, one page displays 3 blocks, and the information displayed by each block is from the following The interfaces obtained by the end are different, so is it necessary to let the front end adjust the interface of the back end 3 times?
Certainly not, the backend can pack the information of 3 blocks into an interface and return them all, then the problem comes, the backend calls 3 interfaces, for example, the first interface takes 1 second, the second takes 2 seconds, and the second Three need 3 seconds, so the response time of the packaged interface is at least 6 seconds. How to solve this problem, we can use multithreading to help us solve it.
Start 3 threads, each thread calls an interface, then the execution time of the 3 threads is the execution time of the slowest thread, so the response time of the interface becomes 3 seconds, which saves half the time .
So the question is, how does the thread return the result of the executed business code? At this time callable is used.
 

    FutureTask futureTask=new FutureTask(new Callable() {         @Override         public String call() throws Exception {             Thread.sleep(3000);             System.out.println("calld method executed");             return "call method return value";         }     });     futureTask.run();     System.out.println("Get return value: " + futureTask.get());     FutureTask futureTask1=new FutureTask(new Callable() {         @Override         public String call() throws Exception {             Thread.sleep(3000);             System.out.println("calld method executed 1");             return "call method return value 1";         }     });

















    futureTask1.run();
    System.out.println("Get return value 1: " + futureTask1.get());
 

We can call the futureTask.get() method to obtain the asynchronous execution result of the thread.
At this time, the problem arises again.
If the two threads execute together, the execution of futureTask is completed, and there will be no problem if futureTask1 is not executed. Is it because futureTask1 can't get the result?
Of course not, the futureTask.get() method will ensure that the thread is blocked until it finishes executing.
Let's look at the futureTask source code

 Two of them, one with time and one without time, will eventually call the awaitDone() method, let’s continue to look at awaitDone

 

 

If the thread has not finished executing, that is, it has not reached the COMPLETING state, it will execute LockSupport.park to make the thread wait. When will it wake up?
let's keep watching 

 

 

 

 

 Finally return the execution result of the thread:

 

So what is the connection between callable and Runnable?
I believe that everyone understands through the analysis of the source code that the call() method of callable is called by the run() method of Runnable.

 

 

Guess you like

Origin blog.csdn.net/zhangjianming2018/article/details/126423361