Interrupting a Runnable with a method of the class
Solution 1
What you want to do - implementing a stop()
method inside a Runnable
- may actually introduce some confusion in the structure of your code. Why? A Runnable
object is, by design, something which holds the code that has to run. But adding a stop()
method would go beyond the sole responsibility of a Runnable
object: that is, you will make it able to control the execution of your code. That should be avoided.
Here is a hint: there is no start()
method in Runnable
. Indeed, there is one in the Thread
class, and the Runnable
interface has been introduced in the JDK to reduce coupling between the "runnable" code and the object which controls its execution (an instance of Thread
).
My question is: why aren't you satisified with the future.cancel()
? Could you please add some precisions in your design requirements?
Solution 2
public class MyRunnable implements Runnable {
private Thread currentThread;
@Override
public void run() {
currentThread = Thread.currentThread();
// Do here something interruptible
}
public void interrupt() {
if (currentThread != null)
currentThread.interrupt();
}
}
But as it has been said, it's bad architecture since you're mixing responsibilities of WHAT is being done (Runnable) with HOW it's being done (execution)
Solution 3
You can create your own class the implements Runnable
and also another interface:
public interface StoppableRunnable extends Runnable {
public void stop();
}
And use this type of Runnable
which is guaranteed to have a stop()
method which you can call.
Example of use:
public MyRunnable implements StoppableRunnable {
private volatile boolean stopped = false;
public void run() {
while(!stopped) { // Do something.... }
}
public void stop() {
stopped = true;
}
}
Zanapher
Updated on August 29, 2022Comments
-
Zanapher over 1 year
How can I write a method of a class implementing the
Runnable
interface (started from anExecutorService
) that would interrupt the thread?I know that I can use
Future fut = es.submit(foo);
(wherees
is theExecutorService
andfoo
is an instance of my class) and then callfut.cancel(true);
from inside the main function of the application, but how do I call something like that from inside the class itself?I would like to have in my Runnable class a method
public void stop() {…}
so that I can call
foo.stop()
from anywhere (including from the main function of the application) and it will work as if I had used theFuture.cancel
function (it has to raise ÌnterruptedException` if the thread is awaiting to acquire a Semaphore). -
Zanapher over 10 yearsI understand your explanation as to why it's not good to have a Runnable that stops itself. I prefer to use a Runnable and start it from an ExecutorService because that way I have threads that were started from a same object, and the ExecutorService can shut them down when needed (and also control the number of such threads started at the same time). I ended up writing a stop method that was passed the Future as argument from the main class. It worked and was more or less what I wanted, but it might not have been a proper use of Runnables.
-
Zanapher over 10 yearsThis doesn't seem to solve my problem since it wouldn't send an interruption to the Runnable. In my main loop, the thread is mostly stuck waiting on Semaphores, so I need the stop method to make it stop waiting and raise an exception in order to go back to the start of the loop and seeing that it has been stopped.