Java multithreading has two important interfaces, Runnable and Callable, which provide a run method and a call method respectively, and there are big differences between them.
1) Runnable provides a run method, and cannot throw exceptions through throws. All CheckedExceptions must be handled inside the run method. Callable provides a call method to directly throw an Exception exception.
2) Runnable's run method has no return value, Callable's call method provides the return value to represent the result of the task running
3) Runnable can be executed as a parameter of the Thread constructor, by opening a new thread, or through a thread pool. Callable can only be executed through thread pool.
1. Runnable usage scenarios
1) Open a new thread as a construction parameter of Thread. The following is a commonly used method of creating threads through anonymous internal classes.
Thread thread = new Thread(new Runnable() { @Override public void run() { ("I am a runnable task"); } }); ();
2) Since Java only provides single inheritance, when creating threads, the specific logic of the run method is generally implemented by implementing the Runnable interface. Then instantiate it and start the thread as the constructor parameter of Thread.
class RunnableTask implements Runnable { @Override public void run() { ("I am a runnable task"); } }
Main method:
RunnableTask runnableTask = new RunnableTask(); Thread thread1 = new Thread(runnableTask); ();
In fact, the essence of 1) and 2) is the same.
3) Submit it to the thread pool as a thread task and is executed through the worker thread maintained by the thread pool.
ExecutorService executor = (); RunnableTask runnableTask = new RunnableTask(); (runnableTask); ();
2. Callable usage scenarios
Because Callable's call method provides the return value, Callable is a good choice when you need to know the result of the task execution. The implementation of Callable is simple.
The following two Callable tasks return the sum of false and integers 0 to 520 respectively.
class BooleanCallableTask implements Callable<Boolean> { @Override public Boolean call() throws Exception { return false; } }
class IntegerCallableTask implements Callable<Integer> { @Override public Integer call() throws Exception { int sum = 0; for (int i = 0; i < 520; i++) { sum += i; } return sum; } }
Callable tasks are submitted through the submit method of the thread pool. And the submit method returns the Future object, and the specific calculation results can be obtained through the Future get method. And get is a blocking method. If the task has not been executed, it will wait.
ExecutorService executor = (); IntegerCallableTask integerCallableTask = new IntegerCallableTask(); Future<Integer> future = (integerCallableTask); (); try { (()); } catch (InterruptedException e) { (); } catch (ExecutionException e) { (); }
3. About Future and FutureTask
For Calleble, Future and FutureTask can be used to obtain task execution results, but Future is an interface. FutureTask is a specific implementation of Future. Moreover, FutureTask also indirectly implements the Runnable interface, which means that FutureTask can be submitted to the thread pool as a Runnable task.
The following is a specific example to demonstrate the various usage methods of FutureTask.
static class Task implements Callable<Integer> { @Override public Integer call() throws Exception { ("The child thread is performing calculations"); (1000); int sum = 0; for (int i = 0; i < 10000; i++) sum += i; return sum; } } public static void main(String[] args) throws InterruptedException { ExecutorService executor = (); //Use FutureTask Callable<Integer> task = new Task(); FutureTask<Integer> futureTask = new FutureTask<Integer>(task); (futureTask); //Use Future// Callable<Integer> call = new Task(); // Future<Integer> future = (call); (); ("The main thread is executing tasks"); (2000); try { ("task run result" + ()); //() } catch (InterruptedException e) { (); } catch (ExecutionException e) { (); } ("All tasks are completed"); }
In this example, using Future and FutureTask are the same, and both can obtain the same calculation results.
This is the end of this article about the difference and connection between Runnable and Callable in Java. For more information about the differences between Runnable and Callable, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!