在java中检查另一个线程布尔值的性能哪个更好
Posted
技术标签:
【中文标题】在java中检查另一个线程布尔值的性能哪个更好【英文标题】:Which one is better for performance to check another threads boolean in java 【发布时间】:2012-02-13 17:09:58 【问题描述】:while(!anotherThread.isDone());
或
while(!anotherThread.isDone())
Thread.sleep(5);
【问题讨论】:
我相信他不是在等待另一个线程完成,而是在等待它发出完成某些任务的信号。所以 Thread.join() 是不合适的。也许你可以更具体地说明你想要做什么 Vig? @jlewis42 我完全知道使用 Thread.join 方法我只是想知道是否使用 while(!anotherThread.isDone());将咀嚼大量的处理副 while(!anotherThread.isDone()) Thread.sleep(5); 这样的话,睡觉的肯定会更好。不休眠的只会继续检查,更糟糕的是,与您的工作线程竞争计算资源。 @jlewis42 不,不,不,请不要鼓励开发人员使用 sleep() 循环进行线程间通信!这种情况非常普遍,以至于 sleep() 现在被经验丰富的开发人员广泛描述为一种反模式,即使它有有效的用途(而且线程间通信不是其中之一)。 @Martin James 你觉得用 Thread.yield() 代替 sleep 怎么样? 【参考方案1】:如果您确实需要等待线程完成,请使用
anotherThread.join()
(您可能需要考虑在加入通话中指定超时。)
你绝对不应该像你的第一个 sn-p 那样紧密循环......而且睡 5 毫秒也好不了多少。
如果您不能使用 join
(例如,您正在等待任务完成而不是整个线程),您应该查看 java.util.concurrent
包 - 很可能有一些东西可以满足您的需求。
【讨论】:
'睡 5 毫秒也好不了多少' - 更糟。它具有阻塞信令的所有上下文更改开销,但在布尔集上没有优先级提升,并且还增加了 2.5 毫秒的平均延迟(假设 5 毫秒的睡眠甚至稍微准确)。正是这样的设计让一些开发人员发布了关于 sleep() 是一种反模式的帖子!【参考方案2】:恕我直言,完全避免使用这种逻辑。相反,也许可以使用属性更改侦听器实现某种通知系统。
【讨论】:
+1 用于通知机制,甚至没有提到任何类型的 sleep() 循环。【参考方案3】:正如其他人所说,在这种情况下最好只使用join
。但是,我想概括一下您的问题并提出以下问题:
一般来说,当一个线程正在等待一个依赖于另一个线程的事件发生时,最好:
-
使用阻塞机制(即加入、条件变量等)或
忙着旋转不睡觉或
忙着睡觉?
现在让我们看看每种情况的含义是什么:
-
在这种情况下,使用阻塞调用将有效地使您的线程脱离 CPU,并且在预期事件发生之前不会再次调度它。有利于资源利用(否则线程会浪费 CPU 周期),但如果事件可能非常频繁且以小间隔发生(即上下文切换比事件发生所需的时间更耗时),则效率不高)。事件最终会发生时通常很好,但您不知道多快。
在第二种情况下,您正忙于旋转,这意味着您正在积极地使用 CPU 而没有执行有用的工作。这与第 1 种情况相反:当预计事件很快会发生时它很有用,但否则可能会不必要地占用 CPU。
这种情况是一种权衡。您正忙于旋转,但同时通过放弃 CPU 来允许其他线程运行。这通常用于当您不想使 CPU 饱和,但预计该事件很快就会发生并且您希望确保您仍然几乎实时在那里以在何时捕获它它发生了。
【讨论】:
3) - 用 sleep() 忙着旋转是完全没有希望的。它具有 1) 的所有缺点,平均增加了间隔/2 的延迟。使用内核同步,(即 1),或只是循环,(即 2)。【参考方案4】:我建议使用所有 Java 对象中内置的等待/通知机制(或使用新的 Lock code in Java 5)。
线程 1(等待线程 2)
while(!thread2.isDone())
synchronize(thread2.lockObject)
thread2.lockObject.wait();
线程 2
// finish work, set isDone=true, notify T1
thread2.lockObject.notify();
'lockObject' 只是一个普通的 (Object lockObject = new Object()) -- 所有 Java 对象都支持等待/通知调用。
在最后一次调用 notify() 之后,Thread1 将唤醒,到达 while 的顶部,看到 T2 现在已经完成,然后继续执行。
您应该考虑中断异常等,但使用等待/通知对于此类情况非常有帮助。
如果您使用现有的代码,无论是否有睡眠,您都在消耗大量的循环,什么都不做...这绝不是好事。
附录
我看到很多 cmets 说要使用 join - 如果您正在等待的执行线程将完成,那么是的,使用 join。如果您有两个始终运行的并行线程(例如,生产者线程和消费者)并且它们没有“完成”,它们只是彼此同步运行,那么您可以使用等待/通知范例 I上面提供。
【讨论】:
+1 用于通知机制,(等待/通知),以及用于线程间通信的休眠()循环。【参考方案5】:第二个。
不过更好的是使用线程的join()
方法来阻塞当前线程直到它完成:)。
编辑:
我刚刚意识到,这仅解决了适用于您给出的两个示例的问题,而不是一般问题(如何等待布尔值被另一个线程更改,不一定让另一个线程实际完成)。
为了回答一般问题,我建议不要使用您描述的方法,而是使用here 描述的保护块模式。这样,等待线程不必继续检查条件本身,而可以等待收到更改通知。希望这会有所帮助!
【讨论】:
【参考方案6】:您考虑过:anotherThread.join()
吗?这将导致当前一个被“停放”而没有任何开销,直到另一个终止。
【讨论】:
【参考方案7】:第二个比第一个好,但都不是很好。你应该使用anotherThread.join()
(或anotherThread.join(timeout)
)。
【讨论】:
【参考方案8】:也不要,改用join()
:
anotherThread.join();
// anotherThread has finished executing.
【讨论】:
以上是关于在java中检查另一个线程布尔值的性能哪个更好的主要内容,如果未能解决你的问题,请参考以下文章