Thread、Runnable、Callable、Future、FutureTask,谈谈他们的关系?
2. Callable 、Future 和 FutureTask
我刚开始看到这幅图,感觉 Java 真是麻烦,已经有了 Thread 和 Runnable 这两种创建线程的方式,
为啥又搞这 3 个东西呢?
其实对于 Thread 和 Runable,其 run() 都是无返回值的,并且无法抛出异常,
所以当你需要返回多线程的数据,就需要借助 Callable 和 Future。
2.1 Callable
2.3 Callable 和 FutureTask 的关系
FutureTask 初始化时,Callable 必须作为 FutureTask 的初始化入参:
当执行 FutureTask.run() 时,其实执行的是 Callable.call():
所以,这里又是一个典型的策略模式 !!!
现在我们应该可以很清楚知道 Thread 、Runnable、FutureTask 和 Callable 的关系:
l Thread.run() 执行的是 Runnable.run();
l FutureTask 继承了 Runnable,并实现了 FutureTask.run();
l FutureTask.run() 执行的是 Callable.run();
l 依次传递,最后 Thread.run(),其实是执行的 Callable.run()。
所以整个设计方法,其实就是 2 个策略模式,Thread 和 Runnable 是一个策略模式,FutureTask 和 Callable 又是一个策略模式,最后通过 Runnable 和 FutureTask 的继承关系,将这 2 个策略模式组合在一起。
嗯嗯。。。我们是不是把 Future 给忘了~~
2.4 Future
为什么要有 Future 呢?我再问一个问题,大家可能就知道了。
我们通过 FutureTask,借助 Thread 执行线程后,结果数据我们怎么获取到呢?这里就需要借助到 Future。
我们看一下 Future 接口:
对于 FutureTask,Callable 就是他的任务,而 FutureTask 内部维护了一个任务状态,所有的状态都是围绕这个任务来进行的,随着任务的进行,状态也在不断的更新。
FutureTask 继承了 Future,实现对任务的取消、数据获取、任务状态判断等功能。
比如我们经常会调用 get() 方法获取数据,如果任务没有执行完成,会将当前线程放入阻塞队列等待,当任务执行完后,会唤醒阻塞队列中的线程。
调用 get() 方法获取数据,如果任务没有执行完成,会将当前线程放入阻塞队列等待,当任务执行完后,会唤醒阻塞队列中的线程。