1

我想创建一个方法来安全地停止在循环中运行的线程,允许最后一个循环在将控制权返回给停止器之前完成。

现在,无论我尝试什么,我都会冻结。可能摆脱僵局或诸如此类;Java 不是我常用的环境,因此为什么这可能是另一个等待/通知问题。

boolean isRunning = true;

@Override
public void run() {
    super.run();

    while (isRunning) {
        // Do work...
    }

    synchronized(this) {
        this.notify();
    }
}

public void stopSafely() {
    isRunning = false;

    try {
        synchronized(this) {
            this.wait();
        }
    } catch (InterruptedException ex) {
        // Handle...
    }
}

这种方法的问题(除了我在 上同步的事实this,但这是为了简单起见),如果notify在之前被调用wait,调用者将冻结。

我确信玩我周围的积木synchronized可以解决问题,但我似乎无法获得正确的组合。

任何的想法?

4

4 回答 4

2

只需寻求真正简单的解决方案:

private volatile boolean isRunning = true;

@Override
public void run() {
    while (isRunning) {
        // Do work...
    }
}

public void stopThread() {
    isRunning = false;
}

这基本上是Thread.interrupted()在内部做的,所以你也可以使用它:

@Override
public void run() {
    while (Thread.interrupted()) {
        // Do work...
    }
}

在这种情况下,您必须调用interrupt()线程。

于 2011-12-09T03:49:23.143 回答
1

我希望第二种方法是从与 run 方法不同的线程调用的。我敢打赌。

在这种情况下,将 isRunning=false 放在同步块中就足够了。只有一个线程可以进入在给定监视器上同步的块。

顺便说一句,不要调用 super.run(),它没用,也不是一个好的编程习惯。

于 2011-12-09T03:17:09.597 回答
0

找到了一个更简单的解决方案,它只是阻止isRunning在进行更改时进行检查:

boolean isRunning = true;

@Override
public void run() {
    while (true) {
        synchronized(this) {
            if (!isRunning) break;
        }

        // Do work...
    }
}

public void stopSafely() {
    synchronized(this) {
        isRunning = false;
    }
}
于 2011-12-09T03:16:04.080 回答
0

首先要从 make isRunning volatile 开始。

volatile boolean isRunning = true;

问题是java运行时做了一些优化,即使第一个线程改变了值,值也没有反映在另一个线程中。

于 2011-12-09T03:17:14.327 回答