Runnable, Callable, Future, FutureTask and Applications

Generally, there are only two ways to create a Thread: one is to inherit the Thread, and the other is to implement the Runnable interface. However, these two creation methods have no return value, and you have to use shared variables or other communication methods to get the results processed by the Thread.

It is generally not recommended to create threads by inheriting threads, because Java has only single inheritance and cannot inherit multiple threads. However, Runnable is an interface, so using Runnable can implement multiple interfaces while implementing classes.

Moreover, in the thread pool, if you use Runnable to create threads, you can directly pass the implementation class of Runnable as a parameter to the thread pool and use the thread pool to manage threads!

Java1. After 5, there are Callable and Future, which can provide the results of thread execution!

Next, let's briefly introduce Runnable, Callable, Future and FutureTask.

Runnable:
Runnable is an interface. The code to be executed is written in the run method, but there is no task return interface, and exceptions cannot be thrown.

public class Main {
    static class MyThread extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " run()Method is executing...");
        }
    }

    static class MyRunnable implements Runnable {

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " run()Method execution in progress...");
        }

    }

    public static void main(String[] args) {

        MyRunnable myRunnable = new MyRunnable();
        Thread thread1 = new Thread();
        thread1.start();

        Thread thread2 = new MyThread();
        thread2.start();
        System.out.println(Thread.currentThread().getName() + " main()End of method execution");
    }


}

Callable:
Callable is also an interface. The code to be executed is written in the call method, and the result of execution is returned. Compared with Runnable, it has returned results and can throw exceptions!

Use Callable+FutureTask to get execution results:

public class CallableTest {
    static class MyCallable implements Callable<Integer> {

        @Override
        public Integer call() {
            System.out.println(Thread.currentThread().getName() + " call()Method execution in progress...");
            return 1;
        }

    }

    public static void main(String[] args) {
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new MyCallable());
        Thread thread = new Thread(futureTask);
        thread.start();

        try {
            Thread.sleep(1000);
            System.out.println("Return results " + futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " main()Method execution complete");
    }

}

Future:
Future is also an interface, which can cancel specific Runnable or Callable tasks, judge whether the task has been cancelled, query whether the task is completed, and obtain task results. If it is Runnable, the returned result is null (the following will analyze why Runnable tasks can return results in the future). There are the following methods in the interface. Note that the two get methods block the thread that currently calls get until the result is returned or timeout will wake up the current thread.

    public interface Future<V> {  
        boolean cancel(boolean mayInterruptIfRunning);  //Cancel task
        boolean isCancelled(); //Determine whether the task is cancelled 
        boolean isDone();  //Judge whether the task is completed
        V get() throws InterruptedException, ExecutionException;  //Get task results
        V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;  //Get task results
    }  

Get execution results using Callable+Future:

public class CallableDemo implements Callable<Integer> {  
      
    private int sum;  
    @Override  
    public Integer call() throws Exception {  
        System.out.println("Callable The sub thread starts to calculate!");  
        Thread.sleep(2000);  
          
        for(int i=0 ;i<5000;i++){  
            sum=sum+i;  
        }  
        System.out.println("Callable End of sub thread calculation!");  
        return sum;  
    }  
} 
 public class CallableTest {  
          
        public static void main(String[] args) {  
            //Create thread pool  
            ExecutorService es = Executors.newSingleThreadExecutor();  
            //Create Callable object task  
            CallableDemo calTask=new CallableDemo();  
            //Submit tasks and get execution results  
            Future<Integer> future =es.submit(calTask);  
            //Close thread pool  
            es.shutdown();  
            try {  
                Thread.sleep(2000);  
            System.out.println("The main thread is performing other tasks");  
              
            if(future.get()!=null){  
                //Output the obtained results  
                System.out.println("future.get()-->"+future.get());  
            }else{  
                //Output the obtained results  
                System.out.println("future.get()No results were obtained");  
            }  
              
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
            System.out.println("The main thread finished executing");  
        }  
    }  

FutureTask:
Because Future is only an interface, it is impossible to create objects directly, so there is FutureTask. FutureTask is not an interface, but a class. It implements the RunnableFuture interface

public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V> //The RunnableFuture interface inherits Runnable and Future

Therefore, FutureTask can be executed by threads as Runnable, and there can be Future operations. Its two constructors are as follows:

    public FutureTask(Callable<V> callable) {  
    }  
    public FutureTask(Runnable runnable, V result) {  
    }  

The code of using Callable+FutureTask to obtain the execution result has been introduced in the Callable section!

Keywords: Java Multithreading

Added by endlyss on Sat, 19 Feb 2022 22:22:23 +0200