展开讨论
首先,第一个发言的哥们是 Pardeep,是在这个问题被提出的 13 天之后:
我没有太 get 到这个哥们回答的点是什么啊。
他说:我们应该去看一下 isDone 方法的描述。
描述上说:如果一个任务已完成,调用这个方法则返回true。而完成除了是正常完成外,还有可能是任务异常或者任务取消导致的完成,这些都算完成。
我觉得他的这个回答和问题有点对不上号,感觉是答非所问。
就当他抛出了一个关于 isDone 方法的知识点吧。
三天后,第二个发言的哥们叫做 Paul,他的观点是这样的:
首先,他说我们不需要检查 INTERRUPING 这个中间状态。
因为如果一个任务处于这个状态,那么获取结果的时候一定是抛出 CancellationException。
叫我们看看 isCancelled 方法和 get 方法。
那我们先看看 isCancelled 方法:
判断任务是否取消(isCancelled)的时候,并没有对 INTERRUPING 这个中间状态做特殊处理。
按照这个逻辑,那么判断任务是否完成(isDone)的时候,也不需要对 INTERRUPING 这个中间状态做特殊处理。
接着,我们看看 get 方法。
get 方法最终会调用这个 report 方法:
如果变量 s (即状态)是 INTERRUPING (值是 5),那么是大于 CANCELLED (值是 4)状态的,则抛出 CancellationException (CE)异常。
所以,他觉得对于 INTERRUPING 状态没有必要进行检测。
因为如果你调用 isCancelled 方法,那么会告诉你任务取消了。
如果你调用 get 方法,会抛出 CE 异常。
所以,综上所述,我认为 Paul 这个哥们的逻辑是这样的:
我们作为使用者,最终都会调用 get 方法来获取结果,假设在调用 get 方法之前。我们用 isCancelled 或者 isDone 判断了一下任务的状态。
如果当前状态好死不死的就是 INTERRUPING 。那么调用 isCancelled 返回 true,那按照正常逻辑,是不会继续调用 get 方法的。
如果调用的是 isDone ,那么也返回 true,就会去调用 get 方法。
所以在 get 方法这里保证了,就算当前处于 INTERRUPING 中间态,程序抛出 CE 异常就可以了。
因此,Paul 认为如果没有必要检测 INTERRUPING 状态的话,那么我们就可以把代码从:
但是,这个哥们还说了一句话来兜底。
他说:Unless i have missed something subtle about the interactions
除非我没有注意到一些非常小的细节问题。你看,说话的艺术。话都被他一个人说完了。
我觉得吧,保罗说的挺有道理的,我赞成他的建议。
但是吧,我也觉得我们在讨论的是一个非常细节,非常小的问题,我不知道,就算现在这样写,会导致任何问题吗?
写到这里,先给大家捋一下:
- Martin 老哥提出 BUG 说 FutureTask#isDone 方法没有判断 INTERRUPING 和 COMPLETING 这个两个中间状态是不对的。
- Paul 同学说,对于 INTERRUPING 这个状态,可以参照 isCancelled 方法,不需要做特殊判断。
- Chris 小老弟说 Paul 同学说的对。
于是他们觉得 isDone 方法应该修改成这样:
好吧,他没有这样说。所以你看,还是要多学学英语,不然我骗了你,你还不知道。
其实他说的是:我认为没有必要做任何改变。
COMPLETING 状态是一个转瞬即逝的过渡状态,它代表我们已经有最终状态了,但是在设置最终状态开始和结束的时间间隙内有一个瞬间状态,它就是 COMPLETING 状态。
其实你是可以通过 get 方法知道任务是否是完成了,通过这个方法你可以获得最终的正确答案。
因为 COMPLETING 这个转瞬即逝的过渡状态是不会被程序给检测到的。
David 靓仔的回答在两个半小时候得到了大佬的肯定: