1

I read many "How to kill a Thread in Java" topics and found one way is to use a boolean volatile variable to indicate whether the Thread should continue running but I've not yet seen an answer that explained how to use this variable properly in both classes (the underlying and the Runnable)

Based on my understanding right now I would do it like that:

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) {...}
        ...
    }

}

My questions: Should I give the isRunning variable to the Thread's Runnable as an argument like I'm doing? And also inside the Runnable class I should define this variable as a volatile? Anything else to modify to make the code better?

tom
  • 2,137
  • 2
  • 27
  • 51

1 Answers1

4

Your code copies the value of isRunning variable. See a question about this.

You either-or need to provide whole Server to runnable, or have process otherwise refer to Server's isRunning field.

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()) {...}
        ...
    }

}

Explaination: the Runnable's thread calls isRunning, what accesses the volatile variable, so you always get the fresh value.

Alternative: use synchronized, protecting writes/reads to the field in Server. Result from your PoV is the same.

Alternative 2: use AtomicBoolean in Server and you can pass a reference to it, instead of whole server. Wouldn't do that though, it smells a bit like exposing (Server's) internals IMHO.

Adam Kotwasinski
  • 4,377
  • 3
  • 17
  • 40
  • Is it a good practice to provide the whole `Server` to the Runnable? Isn't it a little wasteful resource-wise? (Let's say I have hundreds or thousands of `Process`es running.) And if inside `Process` I start another Thread, the same thing I should do for that one? You mean like this: `new Thread(new Process(this)).start();`? – tom Nov 03 '17 at 18:09
  • @tom Yes, you need to pass reference to Server all the time, to all the Runnables you create. Regarding wasting resources, this is microoptimization, and that should be done only when needed. – Adam Kotwasinski Nov 03 '17 at 18:59