我们知道,当不使用线程池时,想让A线程在B线程执行完之后执行,需要在A中的某个调用处,调用B.join,但如果使用jdk1.5以后提供的线程池ExecutorService,这个就用不上了,用了会出同步问题,其实这个场景应该是很常见的吧,比如你用多线程并发执行一些操作,当这些操作全部完成时才能进行下一步,这就是需要这个功能了。后来偶然在网上看到有人说用ExecutorService.invokeAll可以实现,测试了一下,确实简单。这个方法的定义如下:
你需要传一个Callable实现类元素的集合给此方法,每个元素就是一个线程了,返回值是线程执行结果的集合,声明的异常,按照文档的说法---if interrupted while waiting, in which case unfinished tasks are cancelled,如果执行时出现了中断异常,其它未执行完的线程会取消,但我经过测试,发现并没有取消,仍旧正常执行了。下面给出个小例子:
逻辑极其简单,启动200个线程,每个线程先生成一个随机数,如果大于5就抛出异常,中止,否则,睡10秒钟,再输出自己的名字。如果输出结果是200条,说明不管有没有线程抛出异常,其它异常仍旧会照常执行,使用完毕后一定要记得shutdown线程池,否则程序一直挂在那儿无法终止。运行结果,done总是在最后一行输出,说明它总是等池里的所有线程执行完后才会执行到这一步,这样你就可以把第二步的逻辑写到这里就行了。解决了很大的问题。