(Future和FutureTask)

Future类

FutureTask叫未来任务,可以将一个复杂的任务剔除出去交给另外一个线程来完成 在这里插入图片描述

Future主要方法

get()

get方法的行为取决于Callable任务的状态,只有以下5种情况:

  1. 任务正常完成:get方法会立刻返回结果
  2. 任务尚未完成:任务还没有开始或进行中,get将阻塞并直到任务完成。
  3. 任务执行过程中抛出Exception:get方法会抛出ExecutionException,这里抛出异常,是call()执行 时产生的那个异常
  4. 任务被取消:get方法会抛出CancellationException
  5. 任务超时:get方法有一个重写方法,是传入一个延迟时间的,如果时间到了还没有获得结果,get方法会抛出TimeoutException

get(long timeout,TimeUnit unit)

如果call()在规定时间内完成任务,那么就会正常获取到返回值,而如果在指定时间内没有计算出结果, 则会抛出TimeoutException

cancel()

  • 如果这个任务还没有开始执行,任务会被正常取消,未来也不会被执行,返回true
  • 如果任务已经完成或已经取消,则cancel()方法会执行失败,方法返回false
  • 如果这个任务已经开始,这个取消方法将不会直接取消该任务,而是会根据参数 mayInterruptIfRunningg来做判断。如果是true,就会发出中断信号给这个任务。

isDone()

  • 判断线程是否执行完,执行完并不代表执行成功。

isCancelled()

  • 判断是否被取消

用线程池的submit方法返回Future对象

首先要给线程池提交任务,提交时线程池会立刻返回一个空的Future容器。当线程的任务一旦执行完, 也就是当我们可以获取结果时,线程池会把该结果填入到之前给我们的那个Future中去(而不是创建一 个新的Future),我们此时可以从该Future中获得任务执行的结果。

/**
 * 案例:演示一个Future的使用方法
 */
public class Demo22Future {
    public static void main(String[] args) {

        ExecutorService service = Executors.newFixedThreadPool(10);
        Future<Integer> future = service.submit(new CallableTask());

        try {
            //等待3秒后打印
            System.out.println(future.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        service.shutdown();
    }

    static class CallableTask implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            Thread.sleep(3000);
            return new Random().nextInt();
        }
    }
}

用FutureTask来创建Future

用FutureTask来获取Future和任务的结果。FutureTask实现Runnable和Future接口 在这里插入图片描述 把Callable实例当作参数,生成FutureTask的对象,然后把这个对象当作一个Runnable对象,用线程池 去执行这个Runnable对象,最后通过FutureTask获取刚才执行的结果。

/**
 * 案例:演示FutureTask的用法
 */
public class Demo23FutureTask {

    public static void main(String[] args) {
        Demo23FutureTask.Task task = new Demo23FutureTask.Task();
        //FutureTask继承Future和Runnalbe接口
        FutureTask<Integer> integerFutureTask = new FutureTask<>(task);

        //new Thread(integerFutureTask).start();

        ExecutorService service = Executors.newCachedThreadPool();
        service.submit(integerFutureTask);

        try {
            System.out.println("task运行结果:"+integerFutureTask.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
    static class Task implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("子线程正在计算");
            Thread.sleep(3000);
            //模拟子线程处理业务逻辑
            int sum = 0;
            for (int i = 0; i < 100; i++) {
                sum += i;
            }
            return sum;
        }
    }
}