You can understand the difference between Callable and Runnable after reading it

Callable

Interface

public interface Callable<V> {
        V call() throws Exception;
}

Test class

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.Callable;

/**
 * @author syw
 * @date 2021 22:00, August 25
 */
public class CallableTest implements Callable<String> {
    private String string;
    public CallableTest(String string) {
        this.string = string;
    }

    @Override
    public String call() throws Exception {
        //The task is blocked for 5 seconds, and the exception is thrown upward
        Thread.sleep(5000);
        return this.string;
    }
//    Exceptions can also be resolved by try catch
//    @Override
//    public String call(){
//        //The task is blocked for 5 seconds, and the exception is thrown upward
//        try {
//            Thread.sleep(5000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        return this.string;
//    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<String> callable = new CallableTest("my callable is ok!");
        FutureTask<String> task = new FutureTask<String>(callable);
        long beginTime = System.currentTimeMillis();
        //Create thread
        new Thread(task).start();
        //Call the get() method to block the main thread
        String str = task.get();
        long endTime = System.currentTimeMillis();
        System.out.println("hello :"+ str);
        System.out.println("time :"+ (endTime - beginTime)/1000);
    }

}

Test output: output after an interval of five seconds

Runnable

Interface

public interface Runnable {
        void run();
}

Test class

public class RunnableTest implements Runnable{
    private String str;

    public RunnableTest(String str) {
        this.str = str;
    }
    @Override
    public void run() {
        try {
            //The thread is dormant for 5s, and an exception occurs. It can only be solved internally and cannot be thrown up
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Output after 5s
        System.out.println("hello:" + this.str);
    }
    public static void main(String[] args) {
        Runnable runnable = new RunnableTest("my runnable is ok");
        Long beginTime = System.currentTimeMillis();
        Thread thread=new Thread(()->{
            runnable.run();
        });
        thread.start();
        Long endTime = System.currentTimeMillis();
        //First output
        System.out.println("time: " + (endTime-beginTime)/1000);
    }

}

Test results:

The difference between the two

1. The biggest difference is that runnable has no return value, while the task thread implementing the callable interface can return the execution result
2. The run method in the callable interface implementation class allows exceptions to be thrown upward and can be handled internally. try catch, but the exceptions of the run method in the runnable interface implementation class must be handled internally and cannot be thrown

Supplementary Executor framework

The Executor framework consists of tasks, task execution, and asynchronous calculation results

  1. Executor is an interface, which is the basis of executor framework. It separates task Submission from task execution
    Come on;
  2. ThreadPoolExecutor is the core implementation class of thread pool, which is used to execute the submitted task;
  3. ScheduledThreadPoolExecutor is an implementation class that can run commands after a given delay or execute them periodically
    Line command. ScheduledThreadPoolExecutor is more flexible and powerful than Timer;
  4. The Future interface and the FutureTask class implementing the Future interface represent the results of asynchronous calculation;
  5. The implementation classes of Runnable interface and Callable interface can be executed by ThreadPoolExecutor or scheduled ThreadPoolExecutor;
    Schematic diagram of frame usage:

    Explanation of frame use:

1. The main thread must first create a task object that implements the Runnable or Callable interface. The tool class Executors can put a
A Runnable object is encapsulated as a callable object (Executors.callable (Runnable task) or
Executors.callable(Runnable task,Object resule)).
2. Then you can give the Runnable object directly to ExecutorService (ExecutorService.execute (Runnable
command)); Alternatively, you can submit the Runnable object or Callable object to ExecutorService for execution (ExecutorService.submit (Runnable task) or ExecutorService.submit (Callabletask)).
3. If ExecutorService Submit (...), ExecutorService will return an object that implements the Future interface
(in the JDK so far, the FutureTask object is returned). Since FutureTask implements Runnable, programmers can also
To create FutureTask, and then directly hand it over to ExecutorService for execution.
4. Finally, the main thread can execute futuretask Get () method to wait for the task execution to complete. The main thread can also execute
FutureTask.cancel (boolean mayInterruptIfRunning) to cancel the execution of this task.

... that's all

Keywords: Java Interview

Added by ashii on Sun, 19 Dec 2021 13:40:39 +0200