背景
技术群里抛来一个问题:
如果我使用java多线程 同时执行两个线程 哪个线程先结束就使用哪个的结果 这个怎么实现
回答有几种:
Jobs Jia said:
两种方式,
1、线程里直接调你的后续流程,流程里做好幂等控制。
2、线程池返回 future,第一个get成功的 就执行,然后不等第二个
Wang 鹅 showed me the code:
image.pngWang 鹅‘s brother Wang Happy agressed with him
你的思路是对的
But the questioner said nothing...
以上观点都OK。
说下我对这个问题的看法
作为一个后端老人,在线程协调之外,我想到的是任务设计的问题。
由于题目没有太多介绍,以下开始YY。
核心主旨是’哪个先结束,用哪个的结果‘。
那么,可见更看中性能。
任务无外乎两种,计算型、IO型
如果是IO型,放到2个线程里,不合适,意义也不大。
如果是简单计算型,DB操作这种,貌似没有太多讨论的意义,2个任务的处理时间,不会差太多。
以下主要讨论密集计算型,相应的,题目应该扩展一下,先执行完的线程提交结果,DoNext,而未执行完的线程应该尽快停止无谓的计算,减少不必要的资源浪费。
那么问题就涉及到了如果优雅有效的对线程进行中断。
打字好累,不扯了,直奔主题:Interrupt
Java的中断是一种协作机制,目的是做好任务的取消。
举个例子,本人觉得非常贴切。
岳飞抗金。
岳家军在行进途中,突然朝廷撤了他的职,也非不会立刻收到这个通知的,这个要发信到各级机构,信息传输也需要时间,等岳飞经过沿途的停靠点要进行短暂修整,才会收到通知,这时候岳飞要自己决定停止行动,并退出。
如果岳飞行进途中不停歇,他就不知道撤他职的信息。为啥朝廷没有直接通知他,因为没有了,好吧,我编不下去了。。。
中断相关的设计要点
线程执行的结果有两种
- 正常完成和结束
- 完成之前被终止
检查点
有两种方式,官方的是第一种
阻塞,被动中断
为啥Thread.sleep(1),会要求开发者catch一个InterruptedException呢,因为阻塞等待,可能会被打算。
JDK都有哪些阻塞点?
Thread.sleep()和Object.wait()
JUC和NIO部分类会有
image.png
轮询,主动查询
for(分批处理) { //比如要对100W个向量进行计算,可以每批计算50个
if(checkIsInturrepted()) {
doNothing();
return;
}
compute();
}
中断通知
中断的本质是通知
Thread.interrupt()到底做了啥,就是通知,写一个标志位,完了。
image.png
至于目标线程,要不要终止任务,外部无法干预。
中断响应
image.png可以翻看JDK关于这方面的源码,会发现有大量这样的写法,是为了检测到终端操作,重置中断信号,不能吞掉,否则会影响其他组件的响应。
状态检查
Thread.currentThread().isInterrupted()
优雅停止
排水或者打个标
catch (InterruptedException ie) {
interrupted = true;
}
向外通知
依托异常处理机制,继续抛,让上层知道
finally {
if (interrupted)
Thread.currentThread().interrupt();
}
结论:为响应中断而进行任务的设计
这是一种良好的编程习惯
未完待续。。。
网友评论