多线程之串行实现
比如有这么个需求:有线程A、B。A线程是搬砖,B线程是盖房,B必须在A完成后执行。怎么办?
一、用Thread的join方法
join中参数为启动banzhuanThread的线程等待banzhuanThread执行的时间,时间到达后,代码接着往下执行。参数缺省时会一直等待时间无穷,直到执行完成。
如果搬砖的人半路不干了(线程A未按理想情况完成),砖没搬完,就不能开始盖房,此时join方法就不适合这种场景了。接下来就需要用到Future/FutureTask,它们能告诉你搬砖是正常完成还是其他特殊情况。
二、用Future或FutureTask:
先简单对比一下Future和FutureTask:
相同点:
1)、Future和FutureTask都可以通过调用get(),获得Callable中返回的结果,并且该方法是线程阻塞的;
不同点:
1)、Future是个接口,用来展现异步执行的结果;
2)、FutureTask是个类,实现了RunnableFuture接口(RunnableFuture又同时继承了Runnable和Future接口);不难看出,FutureTask比Future多了个Runnable。这也就意味着在使用上存在一些的不同。
再来看两个简单的例子:
首先我们自定义一个BanzhuanCallable实现Callable接口。Callable接口类似Runnable,两者都是用于多线程。最重要区别是:Runnanble不返回线程执行结果并且也无法抛出受检异常。而,Callabel却可以。
搬砖Callable1、用FutureTask实现:
由于FutureTask实现了Runnable接口,所以可以直接传参给Thread构造方法,并调用start执行。
用FutureTask实现2、用Future实现:
Future实现需用到线程池(这里为了方便直接用的Executors.newCachedThreadPool(),大家可以自行单例化一下)。
用Future实现当然,例子1中new Thread也可以换成线程池,调用execute/submit方法。
补充一个知识点:
线程池的submit传参可以是Runnable,也可以是Callable。最后都会转换成RunnableFuture(FutureTask就是实现的这个接口)。
java线程池源码部分 java线程池源码部分上面讲了这么多,提到Callable、Runnable、Future、FutureTask、线程池submit方法。这几者之间的关系大家结合上面例子,稍微思考一下,应该就很清晰了。
希望本文能够帮到大家!