如何正确使用 volatile 来杀死线程?

How to use volatile properly for thread killing purposes?

我阅读了许多 "How to kill a Thread in Java" 主题并发现一种方法是使用布尔型易失性变量来指示线程是否应该继续 运行 但我还没有看到解释如何继续的答案在 classes(底层和 Runnable)

中正确使用这个变量

根据我现在的理解,我会这样做:

public class Server {

    private volatile boolean isRunning = true;

    public Server(...) { }

    public static void main(...)
        ...
        new Thread(new Process(isRunning)).start();
        ...
    }

    public void shutdown() {
        isRunning = false;
    }

}

public class Process implements Runnable {

    private volatile boolean isServerRunning;

    public Process(boolean isServerRunning) {
        this.isServerRunning = isServerRunning;
    }

    @Override
    public void run() {
        ...
        while(isServerRunning) {...}
        ...
    }

}

我的问题:我是否应该像我所做的那样将 isRunning 变量作为参数提供给线程的 Runnable?而且在 Runnable class 里面我应该把这个变量定义为 volatile 吗?还有什么要修改以使代码更好吗?

您的代码复制了 isRunning 变量的值。 See a question about this.

您或者需要提供完整的 Server 以运行,或者有进程,否则请参考服务器的 isRunning 字段。

例如

public class Server ... {
    private volatile boolean isRunning = true;
    public boolean isRunning() { return this.isRunning; }
    ...
}

public class Process implements Runnable {

    private final Server server;

    public Process(Server server) {
        this.server = server;
    }

    @Override
    public void run() {
        ...
        while(server.isRunning()) {...}
        ...
    }

}

解释:Runnable 的线程调用 isRunning,什么访问 volatile 变量,所以你总是得到新的值。

备选方案:使用synchronized,将writes/reads保护到服务器中的字段。您的 PoV 结果相同。

备选方案 2:在服务器中使用 AtomicBoolean,您可以传递对它的引用,而不是整个服务器。虽然不会这样做,但它闻起来有点像暴露(服务器的)内部结构恕我直言。