我开始阅读有关如何安全地停止,中断,暂停和恢复java线程的内容,我在oracle文档中找到了以下解决方案:
1-如何安全地停止线程:
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
- 要停止线程我可以使用boolean
变量而不是volatile Thread
,但为什么Oracle坚持要对启动的线程影响null?在这样做的背后是否有任何秘密(例如使用终结器分配的解放资源)?
2-如何中断等待很长时间的线程:
public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}
- 我为什么要创建新变量moribund
而不是直接使用waiter.interrupt()
?
3-如何暂停和恢复帖子:
private volatile boolean threadSuspended;
public void run() {
while (true) {
try {
Thread.sleep(interval);
if (threadSuspended) {
synchronized(this) {
while (threadSuspended)
wait();
}
}
} catch (InterruptedException e){
}
repaint();
}
}
public synchronized void mousePressed(MouseEvent e) {
e.consume();
threadSuspended = !threadSuspended;
if (!threadSuspended)
notify();
}
- 为什么在run
方法内添加了循环while (threadSuspended)
,因为我不明白添加循环的目的是什么,我的代码可以编译,没有它正确运行(具有相同的输出结果)。
来源链接http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
答案 0 :(得分:3)
<强> 1 强>
使用本地Thread
变量可防止其他线程在您的对象上调用run()
方法。只有此对象实例表示的线程才能使用run()
方法。通常从不同的run()
手动调用Thread
Thread
方法通常是不好的做法,但肯定是可能的。
<强> 2 强>
这一点需要在第1点的上下文中解释。这部分还考虑了interval
非常长的情况,并且线程需要尽快停止。
您当然需要使引用无效,否则第1部分中的代码将继续循环。但请考虑如果将stop
方法简化为:
public void stop() {
waiter.interrupt();
waiter = null;
}
由于这是从另一个线程执行的,因此它可以以任何方式与run()
方法交织在一起。例如,threadA调用stop()
来停止run()
中的threadB:
在这种情况下,threadB不会立即停止,而是执行另一个休眠循环,这会使stop a thread that waits for long periods
的设置任务失败。在给定的实现中,您首先使null,然后中断,这会阻止这种行为。
第3 强>
简而言之:因为另一个线程可能已经通知了您的代码,而没有设置正确的标志。 notify()
的一般合同是呼叫是无害的(但是无用的呼叫显然会消耗一些资源)。所有线程都应该能够应对虚假的唤醒。