在java中,实现线程的方式不仅仅有runnable接口,Thread类,还有callable接口,但是runnable接口和thread类中,都是没有返回值的。
但是在callable接口的实现中,是可以有值返回的;
经过代码的编写,有两种方法可以取出返回值
具体方法请看如下代码
分别使用 FutureTask 和 线程池完成回调。
源码分析
首先简历线程池可以发现,底层实现是有同步队列的,也就是说线程等待是在队列中完成的
ThreadFactory,线程的制造工厂,线程池等的线程创建都和这个类有关
ThreadPoolExecutor 导入的包
里面可以看到有abstractqueuedSynchronizer aqs,和lock锁,还有condition条件控制类
接下来进一步观察线程池是底层怎么实现线程的切换,和锁的应用
2.1 runnable和callable的区别
runnable和callable都可以用来编写多线程程序,两者的区别在于:
1.实现了runnable接口后无法返回结果信息,实现了callable接口后有返回值。
2.实现了runnable接口异常无法通过throws抛出异常,实现了callable接口后可以直接抛出Exception异常
2.2 Future是什么?
在使用callable接口实现多线程时,我们会用到FutureTask去获取返回值,那么Future和FutureTask是什么?
Future是一个获取异步计算结果的接口,而FutureTask是Future的一个实现类。
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;
}
future接口的源码很简单,它实现了五个方法
boolean cancel(boolean mayInterruptRunning) :如果任务还没开始,执行cancel(…)方法将返回false;如果任务已经启动,执行cancel(true)方法将以中断执行此任务线程的方式来试图停止任务,如果停止成功,返回true;当任务已经启动,执行cancel(false)方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时返回false;当任务已经完成,执行cancel(…)方法将返回false。mayInterruptRunning参数表示是否中断执行中的线程。
boolean isCanceller() :如果任务完成前被取消,则返回true。
boolean isDone() :如果任务执行结束,无论是正常结束或是中途取消还是发生异常,都返回true。
V get() :获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。
V get(Long timeout , TimeUnit unit) :获取异步执行结果,如果没有结果可用,此方法会阻塞,但是会有时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常。
总结起来Future实现以下几个功能:可以中断正在执行的任务、可以判断任务是否还在执行、可以获取到任务执行后的结果。FutureTask是Future接口一个比较常用的实现类