what is the advantage of using FutureTask over Callable?

前端 未结 3 1515
野趣味
野趣味 2020-12-25 13:15

There are two approaches to submitting and polling task for result

FutureTask futureTask = new FutureTask(callable);
3条回答
  •  借酒劲吻你
    2020-12-25 13:49

    Using Future we can find out the status of the Callable task and get the returned Object. It provides get() method that can wait for the Callable to finish and then return the result.

    Future provides cancel() method to cancel the associated Callable task. There is an overloaded version of get() method where we can specify the time to wait for the result, it’s useful to avoid current thread getting blocked for longer time. There are isDone() and isCancelled() methods to find out the current status of associated Callable task.

    Here is a simple example of Callable task that returns the name of thread executing the task after one second. We are using Executor framework to execute 100 tasks in parallel and use Future to get the result of the submitted tasks.

        import java.util.ArrayList;
        import java.util.Date;
        import java.util.List;
        import java.util.concurrent.Callable;
        import java.util.concurrent.ExecutionException;
        import java.util.concurrent.ExecutorService;
        import java.util.concurrent.Executors;
        import java.util.concurrent.Future;
    
        public class MyCallable implements Callable {
    
            @Override
            public String call() throws Exception {
                Thread.sleep(1000);
                //return the thread name executing this callable task
                return Thread.currentThread().getName();
            }
    
            public static void main(String args[]){
                //Get ExecutorService from Executors utility class, thread pool size is 10
                ExecutorService executor = Executors.newFixedThreadPool(10);
                //create a list to hold the Future object associated with Callable
                List> list = new ArrayList>();
                //Create MyCallable instance
                Callable callable = new MyCallable();
                for(int i=0; i< 100; i++){
                    //submit Callable tasks to be executed by thread pool
                    Future future = executor.submit(callable);
                    //add Future to the list, we can get return value using Future
                    list.add(future);
                }
                for(Future fut : list){
                    try {
                        //print the return value of Future, notice the output delay in console
                        // because Future.get() waits for task to get completed
                        System.out.println(new Date()+ "::"+fut.get());
                    } catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                }
                //shut down the executor service now
                executor.shutdown();
            }
        }
    

    Where as FutureTask is base concrete implementation of Future interface and provides asynchronous processing. It contains the methods to start and cancel a task and also methods that can return the state of the FutureTask as whether it’s completed or cancelled. We need a callable object to create a future task and then we can use Java Thread Pool Executor to process these asynchronously.

    Let’s see the example of FutureTask with a simple program.

    Since FutureTask requires a callable object, we will create a simple Callable implementation.

        public class MyCallable implements Callable {
    
        private long waitTime;
    
        public MyCallable(int timeInMillis){
            this.waitTime=timeInMillis;
        }
        @Override
        public String call() throws Exception {
            Thread.sleep(waitTime);
            //return the thread name executing this callable task
            return Thread.currentThread().getName();
        }
    
    }
    
        import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.FutureTask;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.TimeoutException;
    
    public class FutureTaskExample {
    
        public static void main(String[] args) {
            MyCallable callable1 = new MyCallable(1000);
            MyCallable callable2 = new MyCallable(2000);
    
            FutureTask futureTask1 = new FutureTask(callable1);
            FutureTask futureTask2 = new FutureTask(callable2);
    
            ExecutorService executor = Executors.newFixedThreadPool(2);
            executor.execute(futureTask1);
            executor.execute(futureTask2);
    
            while (true) {
                try {
                    if(futureTask1.isDone() && futureTask2.isDone()){
                        System.out.println("Done");
                        //shut down executor service
                        executor.shutdown();
                        return;
                    }
    
                    if(!futureTask1.isDone()){
                    //wait indefinitely for future task to complete
                    System.out.println("FutureTask1 output="+futureTask1.get());
                    }
    
                    System.out.println("Waiting for FutureTask2 to complete");
                    String s = futureTask2.get(200L, TimeUnit.MILLISECONDS);
                    if(s !=null){
                        System.out.println("FutureTask2 output="+s);
                    }
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }catch(TimeoutException e){
                    //do nothing
                }
            }
    
        }
    
    }
    

提交回复
热议问题