如何安全地停止我的“类实现 Runnable”?
Posted
技术标签:
【中文标题】如何安全地停止我的“类实现 Runnable”?【英文标题】:How can I safely stop my "class implements Runnable"? 【发布时间】:2016-03-07 07:13:40 【问题描述】:Oracle Java SE Docs 建议这样做:
您可以避免使用 Thread.stop,方法是将小程序的停止和运行方法替换为:
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();
有没有办法为class blinker implements Runnable
做同样的事情?
由于您必须使用blinker thisClass = this;
或类似名称,(blinker == thisClass)
不会总是评估为真吗?
或者这段代码就足够了:
class blinker implements Runnable
boolean stop = false;
@override
public void run()
while (!Thread.currentThread().isInterrupted())
// code
// ...
if (stop) Thread.currentThread().interrupt();
// ...
【问题讨论】:
我.. 不相信 Oracle 建议这样做。通常的方式是Thread.interrupt()
。不,Runnable
没有等价物,只需酌情使用 Thread.interrupt()
或 Future.cancel(true)
。
@markspace I wouldn't have believed it either
我刚刚读到了。这似乎是一个可怕的想法。仅仅因为它是 Oracle 并不意味着他们不能发布经过深思熟虑的代码。我认为这里的主要思想是“不要调用 Thread.stop()”。其他任何东西都是杂物。 OP:使用 Thread.interrupt().
所以内部带有Thread.currentThread().interrupt()
的while (!Thread.currentThread().isInterrupted())
是完全安全的吗?
@markspace 在文档中的那个时候,他们没有覆盖被阻塞的线程。该页面的下一部分将介绍中断。这部分解释了停止的替代方法,虽然没有以最好的方式解释,但了解它非常重要。我同意文档写得很糟糕。
【参考方案1】:
你可以做这样的事情:
class Blinker implements Runnable
Runnable blinker = this;
public void stop()
blinker = null;
public void run()
while(blinker == this)
但这将毫无意义。 我认为您没有理解文档试图传达的观点,即不要使用无限循环来保持线程处于活动状态,使用Thread#stop()
来终止它们。相反,请使用条件,然后在您想要结束保持线程活动的循环时将其设置为 false。
您无需不断检查Thread#isInterrupted()
来保持线程处于活动状态。
while(!stop)
会很好。您也不应该从线程内部中断线程。中断的目的是结束暂停线程的任务。这些任务被包围在try/catch
中,它捕获了InterruptedException
。其他线程通常负责中断。
文档是指允许线程优雅地死掉。
在第一个示例中,run()
方法通过无限循环处理:while(true)
。停止线程的唯一方法是强制某种停止,例如 usong Thread#stop
:
public void run()
while (true)
try
Thread.sleep(interval);
catch (InterruptedException e)
repaint();
但不建议使用Thread#stop
。相反,循环应该依赖于boolean
,另一个线程(或当前线程)可以将其设置为true
或false
:
private volatile boolean running;
public void stop()
running = false;
public void run()
while (running)
try
Thread.sleep(interval);
catch (InterruptedException e)
repaint();
他们没有使用running
布尔值,而是使用blinker == thisThread
,然后在他们想要结束循环时更改了blinker
的值:
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();
【讨论】:
这实际上并没有回答 OP 的问题“如果blinker
是实现 Runnable
的类的实例怎么办?” (释义)。
你为什么要吞下InterruptedException
的?
@dimo414 这是直接来自文档的代码。我只是做了一些修改来显示代码的目的。开始时吞下了异常,我想与文档保持一致。以上是关于如何安全地停止我的“类实现 Runnable”?的主要内容,如果未能解决你的问题,请参考以下文章