我最近遇到了AWT EventQueue
的来源,在那里我看到了这段代码:
final boolean isDispatchThreadImpl() {
EventQueue eq = this;
pushPopLock.lock();
try {
EventQueue next = eq.nextQueue;
while (next != null) {
eq = next;
next = eq.nextQueue;
}
if (eq.fwDispatcher != null) {
return eq.fwDispatcher.isDispatchThread();
}
return (Thread.currentThread() == eq.dispatchThread);
} finally {
pushPopLock.unlock();
}
}
真正困扰我的是使用==
比较线程对象。到目前为止,我一直在使用equals(Object)
执行此操作。我已经看过this question,但这两个答案并不是我想要的。
两个不同的实例是否可能引用相同的本机线程?我应该如何比较线程对象的相等性?
答案 0 :(得分:7)
两个不同的实例是否可能引用相同的本机线程?
没有
根据Thread
javadoc:
线程是程序中执行的线程。
Thread
对象的生命周期分为三个阶段:
在start()
调用之前,Thread
对象表示尚未创建的线程。也许永远不会被创造出来;即如果没有调用start()
。 (此时,没有本机线程。)
在start()
调用之后,直到run()
调用终止,Thread
对象表示实时线程。 (此时,有一个本机线程。)
run()
调用终止后,Thread
对象表示不再存在的线程。 (此时,已删除体现线程的本机线程。)
两个不同的Thread
对象在任何时候都没有任何意义来表示相同的线程;即同一个执行线程。
我应该如何比较线程对象的相等性?
使用==
是正确的方法。
但equals(Object)
也是正确的,因为Thread
从Object
继承了==
,其定义与equals
相同。
关于风格。
有些人认为使用Thread
在风格上更好。但是,在此上下文中,equals
javadoc(实际上)指定==
和Thread
执行相同的操作。实际上,引用相等是唯一对==
对象有意义的等式语义。这是从“线程生命周期”的工作方式,以及两个截然不同的执行线程的事实。 (他们可以始终如一地产生相同的结果,但这是“紧急”行为......并证明行为通常是一个棘手的问题。)
另一方面,这个问题与风格无关。这是关于let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("someViewController")
在这种情况下是否在语义上是正确的。
答案 1 :(得分:2)
这里的第一个关键是:不能有两个相同但具有不同引用的线程。
所以从本质上讲:这是使用检查相同参考的少数情况之一。特别是在不是要比较任意高的"线程对象的数量。你只需要确保"当前" thread是(之前)存储的一些线程引用。
当然,也可以使用ProcessBuilder.redirectOutput(new File("/dev/null"));
来比较线程,也许最好避免让读者感到惊讶。但另一方面,这将更像是一种风格"题;关于你在日常生活中读/写的99%代码可能不常见的一个方面。
并且,正如TJ Crowder正确指出的那样:equals(Object)
转换为Thread.equals(Object)
,其中...对参考相等性进行了简单的检查。这是真正的风格的基础。这是正确的,直到人们开始创建他们自己的Thread子类并提供不同的 equals实现。
最后,第二个关键是:两个Java线程对象不能具有相同的底层本机线程。
答案 2 :(得分:1)
来自JSL-17:
这些线程独立执行对值和操作的代码 驻留在共享主存储器中的对象
这意味着每个线程实例将独立于其他实例执行,尽管数据可以在它们之间共享。因此,两个实例不能引用相同的本机线程。
作为一般情况,您应该更喜欢equals(Object)
来检查相等性。但是,对于Thread
平等,您可以使用==
或equals(Object)
方法。
Thread.equals(Object)
继承自java.lang.Object
的源代码:
public boolean equals(Object obj) {
return (this == obj);
}