Java多线程 Future和FutureTask的区别

时间:2022-11-18 07:17:29

(目录)

一、说明

Future和FutureTask的关系

  • Future 是一个接口,无法直接创建对象,需配合线程池使用.submit()方法返回值Future来保存执行结果;而使用.execute()方法传入Runnable接口无返回值
  • FutureTask 是一个类,可以直接创建对象,其实现了RunnableFuture接口(继承Future接口)

使用区别

  • 就是一个接口和实现类的不同写法

二、理解

Future

  • java.util.concurrent包下Future<V>接口,对RunnableCallable对象执行任务完成后获取执行结果
public interface Future<V> {
    boolean cancel(boolean mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
  • mayInterruptRunning 表示是否中断执行中的线程
  • boolean cancel() 尝试取消任务的执行,如果任务已经完成或已被取消,则返回false;如果任务已经启动,将以中断执行线程的方式停止该任务,停止成功则返回true
  • boolean isDone()若任务完成,则返回true
  • boolean isCancelled() 若任务在完成前取消,则返回true
  • get() 获取执行结果,必须等待任务完成后才返回结果
  • get(long timeout, TimeUnit unit) 获取执行结果,timeout表示等待的最长时间,unit表示时间单位,在指定时间内还没获取到结果,则返回null

FutureTask

  • java.util.concurrent包下实现RunnableFuture<V>接口,可实现Runnable接口执行线程,也可实现Future接口获取执行结果
public class FutureTask<V> implements RunnableFuture<V> {
	……
}
  • RunnableFuture接口继承Runnable
public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

FutureTask执行状态

  • 根据方法执行的时机,FutureTask可处于以下三种行状态

Java多线程 Future和FutureTask的区别

FutureTask方法执行示意图

  • .cancel(ture)会中断线程停止任务,适用于长时间处于运行的任务,并且能够处理interruption
  • .cancel(false)会让线程正常执行至完成,并返回false,适用于未能处理interruption的任务,或者不清楚是否支持取消的任务,以及等待已经开始的任务执行完成

Java多线程 Future和FutureTask的区别

三、实现

1.实现接口

创建CallableThreadDemo类实现Callable接口

public class CallableThreadDemo implements Callable{
    @Override
    public String call() throws Exception {
        System.out.println("Callable子线程: " +Thread.currentThread().getName()+ " 开启");
        return "我是Callable子线程: " +Thread.currentThread().getName()+ " 产生的结果";
    }
}

2.使用Future

创建CallableTest类执行测试,将创建好的线程对象通过.submit()方法提交到线程池去执行,线程执行后,返回值Future可被拿到

public class CallableTest {
    public static void main(String[] args) {
        // 1.创建线程池
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        // 2.创建Callable子线程对象任务
        CallableThreadDemo callableThread_1 = new CallableThreadDemo();
        // 3.提交任务到线程池
        Future future = executorService.submit(callableThread_1);
        // 4.获取执行结果
        try {
            System.out.println("主线程开始执行");

            System.out.println("主线程要取得Callable子线程的结果");
            if (future.get()!=null){
                //输出获取的结果
                System.out.println(future.get());
            }else {
                //输出未获取到结果
                System.out.println("future.get()未获取到结果");
            }
        } catch (InterruptedException e){
            e.printStackTrace();
        }catch (Exception e) {
            e.printStackTrace();
        }
        // 5.关闭线程池
        executorService.shutdown();
        System.out.println("主线程执行完成");
    }
}

Java多线程 Future和FutureTask的区别

3.使用FutureTask

创建FutureTask对象,提交任务到线程池,可以交给Executor执行,或将创建好的线程对象通过.submit()方法提交到线程池去执行,线程执行后,返回值FutureTask可被拿到

public class CallableTest {
    public static void main(String[] args) {
        // 1.创建线程池
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        // 2.创建Callable子线程对象任务
        CallableThreadDemo callableThread_1 = new CallableThreadDemo();
        // 3.提交任务到线程池
        FutureTask futureTask = new FutureTask(callableThread_1);
        executorService.submit(futureTask);
        // 4.获取执行结果
        try {
            System.out.println("主线程开始执行");

            System.out.println("主线程要取得Callable子线程的结果");
            if (futureTask.get()!=null){
                //输出获取的结果
                System.out.println(futureTask.get());
            }else {
                //输出未获取到结果
                System.out.println("futureTask.get()未获取到结果");
            }
        } catch (InterruptedException e){
            e.printStackTrace();
        }catch (Exception e) {
            e.printStackTrace();
        }
        // 5.关闭线程池
        executorService.shutdown();
        System.out.println("主线程执行完成");
    }
}

Java多线程 Future和FutureTask的区别