Java并发35:Callable+Future系列--Future接口学习笔记

1.Future接口概述

Future接口代表着异步计算的结果

Future接口提供了一些方法:查看计算是否完成、等待计算完成和获取计算结果。

只有在计算完成时,才能通过get()方法获取计算结果,必要时程序会阻塞直到计算完成。

取消计算是通过方法cancel()执行的。

此外,还提供了一些其他的方法用于确认任务是否正常(isDone())或者是否取消(isCancelled())。

一旦一个计算已经完成,则这个计算不能再被取消。

如果你因为可取消性而想使用Future接口,但是又不能提供一个可用的计算结果,那么你可以将其声明为Future<?>类型,并且以null值作为返回值。

示例用法

interface ArchiveSearcher {
    String search(String target);
}
class App {
    ExecutorService executor = ...
    ArchiveSearcher searcher = ...

    void showSearch(final String target)
            throws InterruptedException {
        Future<String> future
                = executor.submit(new Callable<String>() {
            public String call() {
                return searcher.search(target);
            }
        });
        displayOtherThings(); // do other things while searching
        try {
            displayText(future.get()); // use future
        } catch (ExecutionException ex) {
            cleanup();
            return;
        }
    }
}

谨记一致性影响:

一个线程池中异步计算的结果 happens-before 另一个线程中Future.get()方法之后的操作。

也就是说: 一个线程池中异步计算的结果 对 另一个线程中 Future.get()方法 之后的操作 可见。

2.Future的方法说明

Future的方法如下:

1.isDone():任务是否完成

2.isCancelled():任务是否取消了

3.cancel(mayInterruptIfRunning):

取消任务:

  • mayInterruptIfRunning = true:如果任务在运行,则即使中断任务,也要取消任务。
  • mayInterruptIfRunning = false:如果任务在运行,则等待任务运行完毕,再取消任务。

4.get():

阻塞的的获取计算结果,直到发生以下三种情况之一

  • 获取了计算结果,返回结果。
  • 当前线程被中断被中断,抛出InterruptedException异常。
  • 计算出错,则抛出ExecutionException异常。

5.get(timeout,TimeUnit):

在限定时间内,阻塞的的获取计算结果,直到发生以下四种情况之一:

  • 获取了计算结果,则返回结果。
  • 当前线程被中断被中断,则抛出InterruptedException异常
  • 计算出错,则抛出ExecutionException异常。
  • 等待时间超时,则抛出TimeoutException异常。

3.实例练习

练习目的:熟悉Future各方法的使用。

练习描述:

isDone()和isCancelled()的使用
cancel(true)的使用
get(timeout,TimeUnit)的使用
get()的使用
实例代码:

//定义一个线程池
ExecutorService executorService = Executors.newCachedThreadPool();
//定义一个Callable对象
Callable callable = new Callable() {
    @Override
    public Object call() throws Exception {
        //模拟开始计算
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            //e.printStackTrace();
            System.out.println("正在计算,被取消了");
        }
        //计算结束,返回结果
        return 100;
    }
};
//提交一个Callable任务,返回一个Future对象
Future<Integer> future = executorService.submit(callable);

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
//isDone():任务是否完成
System.out.println("1000ms的时候计算是否完成:" + future.isDone());
//isCancelled():任务是否取消了
System.out.println("1000ms的时候计算是否取消:" + future.isCancelled());

System.out.println();
//cancel取消-true表示即使在运行也取消,false表示如果没运行可以取消
future.cancel(true);
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
//isDone():任务是否完成
System.out.println("cancel之后计算是否完成:" + future.isDone());
//isCancelled():任务是否取消了
System.out.println("cancel之后计算是否取消:" + future.isCancelled());

System.out.println();
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
//再次提交一个Callable任务,返回一个Future对象
future = executorService.submit(callable);

//在2秒时限内尝试去获取
//获取到则返回结果
//获取不到则返回
try {
    System.out.println("在2秒时限内尝试去获取:" + future.get(2, TimeUnit.SECONDS));
} catch (TimeoutException e) {
    //e.printStackTrace();
    System.out.println("timeout超时,抛出TimeoutException异常");
} catch (InterruptedException e) {
    //e.printStackTrace();
    System.out.println("线程interrupt,抛出InterruptedException异常");
} catch (ExecutionException e) {
    //e.printStackTrace();
    System.out.println("执行出错,抛出ExecutionException异常");
}
//isDone():任务是否完成
System.out.println("get(timeout,TimeUnit)超时之后,计算是否完成:" + future.isDone());
//isCancelled():任务是否取消了
System.out.println("get(timeout,TimeUnit)超时之后,cancel之后计算是否取消:" + future.isCancelled());

System.out.println();
//阻塞的等待计算结果,直到获取计算结果
try {
    System.out.println("阻塞的等待计算结果,直到获取计算结果:" + future.get());
} catch (InterruptedException e) {
    //e.printStackTrace();
    System.out.println("线程interrupt,抛出InterruptedException异常");
} catch (ExecutionException e) {
    //e.printStackTrace();
    System.out.println("执行出错,抛出ExecutionException异常");
}
//isDone():任务是否完成
System.out.println("get()之后,计算是否完成:" + future.isDone());
//isCancelled():任务是否取消了
System.out.println("get()之后,cancel之后计算是否取消:" + future.isCancelled());

//取消线程池
executorService.shutdown();

运行结果:

1000ms的时候计算是否完成:false
1000ms的时候计算是否取消:false

正在计算,被取消了
cancel之后计算是否完成:true
cancel之后计算是否取消:true

timeout超时,抛出TimeoutException异常
get(timeout,TimeUnit)超时之后,计算是否完成:false
get(timeout,TimeUnit)超时之后,cancel之后计算是否取消:false

阻塞的等待计算结果,直到获取计算结果:100
get()之后,计算是否完成:true
get()之后,cancel之后计算是否取消:false

 

posted @ 2021-09-02 19:36  姚春辉  阅读(199)  评论(0编辑  收藏  举报