【问题标题】:How can I safely stop my "class implements Runnable"?如何安全地停止我的“类实现 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)
  • 我刚刚读到了。这似乎是一个可怕的想法。仅仅因为它是 Oracle 并不意味着他们不能发布经过深思熟虑的代码。我认为这里的主要思想是“不要调用 Thread.stop()”。其他任何东西都是杂物。 OP:使用 Thread.interrupt().
  • 所以内部带有Thread.currentThread().interrupt()while (!Thread.currentThread().isInterrupted()) { } 是完全安全的吗?
  • @markspace 在文档中的那个时候,他们没有覆盖被阻塞的线程。该页面的下一部分将介绍中断。这部分解释了停止的替代方法,虽然没有以最好的方式解释,但了解它非常重要。我同意文档写得很糟糕。

标签: java multithreading class runnable


【解决方案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,另一个线程(或当前线程)可以将其设置为truefalse

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 这是直接来自文档的代码。我只是做了一些修改来显示代码的目的。开始时吞下了异常,我想与文档保持一致。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-11
  • 2012-03-16
  • 1970-01-01
  • 2020-04-22
  • 2012-01-07
  • 1970-01-01
  • 2013-10-30
相关资源
最近更新 更多