如何正确使用volatile来进行线程查杀?

时间:2017-11-03 17:35:02

标签: java multithreading volatile

我读了许多&#34;如何用Java杀死一个线程&#34;主题和发现一种方法是使用布尔volatile变量来指示线程是否应继续运行但我还没有看到解释如何在两个类(底层和Runnable)中正确使用此变量的答案< / p>

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

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变量作为参数提供给Thread的Runnable,就像我在做什么一样?而且在Runnable类中我应该将此变量定义为volatile?还有什么要修改以使代码更好吗?

1 个答案:

答案 0 :(得分:4)

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

您要么或者需要提供整个Server来运行,要么让流程引用服务器的isRunning字段。

e.g。

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,保护写入/读取服务器中的字段。 PoV的结果是一样的。

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