这取决于您是否关心所涉及的财产的过去或未来状态。
为了简化语义,应该意识到有一些情况下使用IsXXX形式是值得商榷的,并且有一些非常常见的情况下只有IsXXX形式是有用的。
下面是Thread.IsAlive()的“真值表”,基于线程随时间可能出现的状态。不要考虑线程为什么会翻转状态,我们需要专注于使用的语言。
可能的线程状态随时间变化的情境:
Past Present Future
===== ======= =======
1. alive alive alive
2. alive alive dead
3. alive dead dead
4. dead dead dead
5. dead dead alive
6. dead alive alive
7. dead alive dead
8. alive dead alive
注意:下面我会谈论未来状态以保持一致。知道一个线程是否会死亡很可能是无法预测的,因为这是
停机问题的一个子集。
当我们通过调用方法来询问一个对象时,有一个常见的假设:“在我询问的时候,这个线程是否还活着?对于这些情况,我们只关心“现在”列中的答案,并且使用IsXXX形式是可以的。
情况#1(始终活着)和情况#4(始终死亡)是最简单和最常见的。调用IsAlive()的结果不会在调用之间改变。关于语言的争论是由其他6种情况引起的,在这些情况下,调用IsAlive()的结果取决于何时调用它。
情况#2(将死亡)和情况#3(已死亡)从活动状态转换为死亡状态。
情况#5(将开始)和情况#6(已开始)从死亡状态转换为活动状态。
对于这四个(2、3、5、6),
IsAlive()
的答案不是恒定的。问题变成了,我关心现在的状态,
IsAlive()
,还是我对过去/未来的状态感兴趣,
WasAlive()
和
WillBeAlive()
?除非你能预测未来,否则
WillBeAlive()
调用对于除了最具体的设计之外的所有情况都变得无意义。
处理线程池时,我们可能需要重新启动处于“死亡”状态的线程来服务连接请求,并且它们曾经是否存活并不重要,只要它们目前处于死亡状态即可。在这种情况下,我们实际上可能想使用
WasDead()
。当然,我们应该尽力保证不重新启动刚刚重新启动的线程,但这是一个设计问题,而不是语义问题。假设没有其他人可以重新启动线程,那么使用
IsAlive() == false
或
WasDead() == true
并没有太大区别。
现在来看最后两种情况。方案
#7(曾经死亡,现在存活,将会死亡)实际上与
#6几乎相同。你知道它在未来的什么时候会死吗?10秒钟、10分钟还是10小时?在决定该做什么之前,你会等待吗?不会,你只关心当前(现在)的状态。我们在这里谈论的是命名问题,而不是多线程设计。
方案
#8(曾经存活,现在死亡,将会存活)实际上与
#3几乎相同。如果你正在重复使用线程,那么它们可以循环多次地在存活/死亡状态之间切换。担心
#3和
#8之间的区别回溯到停机问题,因此可以忽略它们。
IsAlive()
应该适用于所有情况。对于
#5和
#6,
IsAlive() == false
可以起作用,而不需要添加
WasAlive()
。
is
前缀比为不同(但非常相似)的用途使用不同的前缀更易读且不易混淆。 - Sasha Chedygov