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?
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.