天天看点

Java并发编程:Callable、Future和FutureTask

在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承thread,另外一种就是实现runnable接口。

  这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。

  如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。

  而自从java 1.5开始,就提供了callable和future,通过它们可以在任务执行完毕之后得到任务执行结果。

  今天我们就来讨论一下callable、future和futuretask三个类的使用方法。以下是本文的目录大纲:

  一.callable与runnable

  二.future

  三.futuretask

  四.使用示例

  若有不正之处请多多谅解,并欢迎批评指正。

  请尊重作者劳动成果,转载请标明原文链接:

  

一.callable与runnable

  先说一下java.lang.runnable吧,它是一个接口,在它里面只声明了一个run()方法:

1

2

3

public interface runnable {

}

  由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。

  callable位于java.util.concurrent包下,它也是一个接口,在它里面也只声明了一个方法,只不过这个方法叫做call():

4

5

6

7

8

9

public interface callable {

  可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的v类型。

  那么怎么使用callable呢?一般情况下是配合executorservice来使用的,在executorservice接口中声明了若干个submit方法的重载版本:

future submit(callable task);

future submit(runnable task, t result);

future<?> submit(runnable task);

  第一个submit方法里面的参数类型就是callable。

  暂时只需要知道callable一般是和executorservice配合来使用的,具体的使用方法讲在后面讲述。

  一般情况下我们使用第一个submit方法和第三个submit方法,第二个submit方法很少使用。

二.future

  future就是对于具体的runnable或者callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

  future类位于java.util.concurrent包下,它是一个接口:

public interface future {

  在future接口中声明了5个方法,下面依次解释每个方法的作用:

cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayinterruptifrunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayinterruptifrunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayinterruptifrunning设置为true,则返回true,若mayinterruptifrunning设置为false,则返回false;如果任务还没有执行,则无论mayinterruptifrunning为true还是false,肯定返回true。

iscancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。

isdone方法表示任务是否已经完成,若任务完成,则返回true;

get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;

get(long timeout, timeunit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。

  也就是说future提供了三种功能:

  1)判断任务是否完成;

  2)能够中断任务;

  3)能够获取任务执行结果。

  因为future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的futuretask。

三.futuretask

  我们先来看一下futuretask的实现:

public class futuretask implements runnablefuture

  futuretask类实现了runnablefuture接口,我们看一下runnablefuture接口的实现:

public interface runnablefuture extends runnable, future {

  可以看出runnablefuture继承了runnable接口和future接口,而futuretask实现了runnablefuture接口。所以它既可以作为runnable被线程执行,又可以作为future得到callable的返回值。

  futuretask提供了2个构造器:

public futuretask(callable callable) {

public futuretask(runnable runnable, v result) {

  事实上,futuretask是future接口的一个唯一实现类。

四.使用示例

  1.使用callable+future获取执行结果

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

public class test {

class task implements callable{

  执行结果:

子线程在进行计算

主线程在执行任务

task运行结果4950

所有任务执行完毕

  2.使用callable+futuretask获取执行结果

38

39

40

41

42

43

44

45

  如果为了可取消性而使用 future 但又不提供可用的结果,则可以声明 future<?> 形式类型、并返回 null 作为底层任务的结果。