There are many solutions to this. Here is one of them:
public class Main {
public static void main(String... args) {
Thread thread = () -> {
while(true) {
// We call Thread.interrupted to check the interrupted status of the Thread.
// This method also clears the interrupted status of the Thread.
if(Thread.interrupted()) {
break;
}
// code...
}
}
Thread timer = () -> {
long start = System.currentTimeMillis();
while(true) {
long current = System.currentTimeMillis();
if(current - start == 10_000){ // underscore for clarity
// This causes the thread to interrupt. The next pass
// in our loop in "thread" will first check its interrupted status
// before continuing, and will break if the status is interrupted
thread.interrupt();
break;
}
}
}
// wrap in synchronized block to ensure both threads run simultaneously
synchronized(Main.class) {
thread.start();
timer.start();
}
}
}
Explanation
In this solution, we use interrupts to make the while-loop in thread
break. An interrupt stops normal thread operation at whatever point it is executing, but only if the thread calls a method that throws InterruptedException
, and the thread returns (or breaks) in the catch block. Thread.interrupt()
sets the interrupt status to interrupted, but does not actually interrupt the Thread from execution. The run
method of thread
is invoked again after being interrupted. Since we check Thread.interrupted()
at the beginning of our loop, the loop will break when the loop is entered, and run
exits and the Thread ceases to run. With Thread.interrupted()
, you have to check, in the same Thread, for its interrupted status, and then choose what to do if the status is cleared or not.
As a side note, if our only branch (if-statement) in the loop checks for the interrupted state of that thread, then it might be easier to read and be more efficient if we simply declare our while-loop as while(!Thread.interrupted())
. Otherwise it should be left as it is.
Other Solutions
Other solutions are illustrated by some other answers here, though some answer your whole problem in a different way. Some other solutions include using an AtomicBoolean as answered by Oliver Dain; another using a global lock object and volatile booleans or AtomicBoolean.
There are many solutions, but the interrupt solution seems to be the easiest and most convenient in most use-cases.