Alternative to Thread.suspend() and .resume()
The correct way to handle interrupting a thread (in this case, to pause or stop it) is, naturally, with Thread#interrupt()
. It is designed so that you can define safe points at which the thread can be interrupted, which for you is naturally the point between each task. So, to avoid having to manually check your variable between each task, and to be able to easily resume where you left off, you can store your tasks as a list of Runnable
s, and remember your position in the list from when you left off, like this:
public class Foo {
public static void runTask(Runnable task) throws InterruptedException {
task.run();
if (Thread.interrupted()) throw new InterruptedException();
}
Runnable[] frobnicateTasks = new Runnable[] {
() -> { System.out.println("task1"); },
() -> { Thread.currentThread().interrupt(); }, //Interrupt self only as example
() -> { System.out.println("task2"); }
};
public int frobnicate() {
return resumeFrobnicate(0);
}
public int resumeFrobnicate(int taskPos) {
try {
while (taskPos < frobnicateTasks.length)
runTask(frobnicateTasks[taskPos++]);
} catch (InterruptedException ex) {
}
if (taskPos == frobnicateTasks.length) {
return -1; //done
}
return taskPos;
}
public static void main(String[] args) {
Foo foo = new Foo();
int progress = foo.frobnicate();
while (progress != -1) {
System.out.println("Paused");
progress = foo.resumeFrobnicate(progress);
}
System.out.println("Done");
}
}
-->
task1
Paused
task2
Done
I could check the boolean between every line of code, but I am hoping for a more elegant solution. Is there a good way to do this?
Unfortunately, no.
To replace pause / resume, what you really need is for one thread to "pause" another thread, without involving the code of the second thread.
This is not possible to do safely in Java as currently spec'd and implemented.
The deprecated Thread methods are the only way for one thread to kill, stop / pause, resume another thread ... if the other thread is not actively cooperating. They were deprecated because (in a nutshell) that kind of control cannot be implemented safely within any current generation mainstream JVM1.
The best you could do is wrap the pause / resume logic in a method that the second thread calls at appropriate points. (This probably should use wait / notify ... or equivalent ... to deal with the resumption. But wait/notify per se does not address your clear requirement for pause/resuming a non-cooperating thread.)
1 - You'd need something like the Isolates API to do this. There have been attempts to implement it in research projects, but AFAIK Isolates has never been implemented in a production JVM.