Callble interface creates multithreading [detailed summary]

Callble interface introduction

Callable is an interface used when creating threads. It is similar to Runnable. Runnable has no return value when creating multiple threads, but Callable has a return value. We generally use Callable when we want multithreading with a return value.

The difference between callble and runable

  • different name
  • The rewriting method is different, the call() method is in Callable, and the run() method is in Runnable
  • With or without generics, where the Callable interface has generics, but the Runnable interface does not have generics
  • Whether there is a return value, among which the Callable interface has a return value, and the return value type is consistent with the generic type
  • The construction methods are different, among which the Callable interface uses the FutureTask class as a medium to contact the Runnable interface

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 what result was returned by that thread. To do this, a Future object can be used.

Think of a Future as an object that holds the result - it might not hold the result for a while, but it will in the future (once the Callable returns). Futures are basically a way the main thread can keep track of the progress as well as the results of other threads. To implement this interface, 5 methods must be rewritten. The important methods are listed here, as follows:

public boolean cancel(boolean mayInterrupt)//:用于停止任务。

It will stop the task if it has not already been started. If started, the task will only be interrupted if mayInterrupt is true.

`public Object get()//抛出 InterruptedException,ExecutionException:用于获取任务的结果`。

If the task is complete, it will return the result immediately, otherwise it will wait for the task to complete and then return the result.

public boolean isDone()://如果任务完成,则返回 true,否则返回 false

You can see that Callable and Future do two things - Callable is similar to Runnable in that it encapsulates a task to be run on another thread, and Future is used to store results obtained from another thread. In fact, futures can also be used with Runnables. To create a thread, a Runnable is required. In order to get a result, a future is required.

FutureTask class

The FutureTask class implements the RunnableFuture interface, and the RunnnableFuture interface inherits the Runnable and Future interfaces, so FutureTask is a task that provides the results of asynchronous calculations.
FutureTask can be used to wrap Callable or Runnbale objects. Because FutureTask implements the Runnable interface, FutureTask can also be submitted to Executor

You can take a look at the source code inside:
FutureTask constructor

// 创建一个FutureTask,一旦运行就执行给定的Callable
public FutureTask(Callable<V> callable) {
    
    
    if (callable == null)
        throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;       // ensure visibility of callable
}
// 创建一个FutureTask,一旦运行就执行给定的Ru你那边了,并安排成功完成时get返回给定的结果
public FutureTask(Runnable runnable, V result) {
    
    
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

Other commonly used codes:

// get()获取结果
public V get() throws InterruptedException, ExecutionException {
    
    
    int s = state;
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    return report(s);
}
// outcome就是返回值
private V report(int s) throws ExecutionException {
    
    
    Object x = outcome;
    if (s == NORMAL)
        return (V)x;
    if (s >= CANCELLED)
        throw new CancellationException();
    throw new ExecutionException((Throwable)x);
}

callable interface creates multithreading

Execution with FutureTask

public class CallableTest {
    
    
    public static void main(String[] args) throws ExecutionException, InterruptedException {
    
    
        new Thread(()->{
    
    
            System.out.println(Thread.currentThread().getName()+"执行Runnable");
        }).start();
        FutureTask<String> task = new FutureTask<>(() -> {
    
    
            System.out.println(Thread.currentThread().getName() + "使用Callable接口");
            return "Callable接口返回值";
        });
        new Thread(task).start();
        System.out.println("Callable返回值:" + task.get());
    }
}


The output is:

Thread-0执行Runnable
Thread-1使用Callable接口
Callable返回值:Callable接口返回值

Summary (emphasis)

1. 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, you can use the Future object to obtain the background job information. Calculation result or execution status.
2. Generally, FutureTask is mostly used for time-consuming calculations, and the main thread can obtain the results after completing its own tasks.
3. The result can only be retrieved when the calculation is complete; if the calculation has not been completed, the get method is blocked. Once a calculation is complete, it cannot be restarted or canceled. get method and the result can only be obtained when the calculation is completed, otherwise it will be blocked until the task enters the completion state, and then the result will be returned or an exception will be thrown.
4. Calculated only once.

Guess you like

Origin blog.csdn.net/weixin_54046648/article/details/128183268