Standard Java pattern for wrapping a timeout around an errant process - java

I'm using a 3rd party function (say runThird()) that has a tendency to loop indefinitely and has no timeout facility built in. However, I can kill it (killThird()). Is there a proper way to do this (i.e. some concurrency construct)?
Here's my attempt at this:
java.lang.Thread thread = new Thread(new Runnable(){
#Override
public void run(){
try {
Thread.sleep(TIMEOUT);
} catch (java.lang.InterruptedException e){
return;
}
killThird();
}
});
thread.start();
RunThirdResult rtr = runThird();
if (thread != null){
thread.interrupt();
}
But I'm not sure I like the overhead of creating a thread, using sleep and the contrivance of interrupting the thread if runThird() returns.

Let's assume runThird() retuns Integer ...
// ... in your class ...
private ExecutorService executor = Executors.newCachedThreadPool();
//... then somewhere, where you want to call runThird()
Future<Integer> handle = executor.submit( new Callable<Integer>(){
#Override Integer call(){
return runThird(); // Assume you made it available here ...
}
}
Integer result;
try{
result = handle.get(TIMEOUT,UNIT); // TIMEOUT and UNIT declared somewhere above ...
}
catch(TimeoutException ex) {
killThird();
// HANDLE result not being set!
}
// ... use result.

I would use a ScheduledExecutorService for this. Schedule it to be killed.
volatile RunThirdResult rtr;
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.schedule(new Runnable(){
public void run(){
if(rtr == null) killThird();
}
}, TIMEOUT_IN_MILLIS, TimeUnit.MILLISECONDS);
RunThirdResult rtr = runThird();

Something like that? The most interesting part is StoppableWrapper#stop(), cause graceful cancellation is a hard thing and there's no common approach for all cases. One time you need to clear filesystem, other time to close network connection, etc. In your sample, you just call interrupt(), so I assumed runThird() honors being interrupted and will take care to clean things behind itself.
class Sample {
final ExecutorService tasksExecutor = Executors.newCachedThreadPool();
class StoppableWrapper implements Runnable {
private final Runnable task;
private final CountDownLatch executed;
StoppableWrapper(Runnable task, CountDownLatch executed) {
this.task = task;
this.executed = executed;
}
void stop() {
// e.g. Thread.currentThread().interrupt()
}
#Override
public void run() {
task.run();
executed.countDown();
}
}
public void scheduleTimingOutTaskExecution(final long timeout) {
final CountDownLatch executed = new CountDownLatch(1);
final StoppableWrapper command = new StoppableWrapper(new RunThirdInstance(), executed);
tasksExecutor.execute(command);
tasksExecutor.execute(new Runnable() {
#Override
public void run() {
try {
if (!executed.await(timeout, TimeUnit.MILLISECONDS)) {
command.stop();
// additionally, you can make stop() return boolean after time-out as well and handle failure
}
} catch (InterruptedException e) {
// handle stopper exception here
}
}
});
}
}

Related

Is this a correct way to stop a thread if it hasn't finished after a set period of time?

public class TimeToDieThread extends Thread implements Runnable
{
private Runnable r;
private long lTimeLength;//time NanoTime
public TimeToDieThread(Runnable r, long lTimeLength)
{
super();
this.r = r;
this.lTimeLength = lTimeLength;
}
public void start() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
boolean bran = false;
while ((!Thread.currentThread().isInterrupted()) && (bran == false)) {
r.run();
bran = true;
}
}
});
t.start();
// Sleep a for entire length, and then interrupt
try
{
Thread.sleep(lTimeLength);
} catch (InterruptedException e)
{
System.out.println("Interrupted, wop wop waa");
}
t.interrupt();
}
}
It is rarely necessary to use Thread directly (and it's definitely not necessary to extend Thread and implement Runnable, because Thread already implements Runnable).
Use an ExecutorService, submit a Runnable to that, and use the get(long, TimeUnit) method on the returned Future to wait for it to complete.
// Construct this somewhere. Note that you also need to shut it down somewhere.
// This is just an example of how you might construct it; other executors are
// available.
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
Future<?> future = executorService.submit(yourRunnable);
future.get(timeout, timeoutUnit); // Exception handling omitted.
// Cancel if it is still running.
future.cancel(true);

Can't stop thread

I have these two methods for creating and stopping a thread. However the thread still keeps running, even after the first method is called. (I'm creating an object of the class and calling them from another class).
private Thread thread;
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
sendAlarm = false;
if (!thread.equals(null)) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void triggerAlarm() {
Runnable alarmTest = new Runnable() {
#Override
public void run() {
while (sendAlarm) {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
}
}
};
thread = new Thread(Test);
thread.start();
}
When stopAlarm is called the thread is always null, although it is called after triggerAlarm is called (thread is running).
Your problem is caused by thread scope. Thread scope is created when you create a thread with same variables in the scope but you can't change these variables from outside world. Best practice for managing runnables in android is to use Handler.
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
after definitions, in order to start the runnable:
handler.post(alarmTest,0); //wait 0 ms and run
in order to stop the runnable:
handler.removeCallbacks(alarmTest);
EDIT: wait statement with loop
EDIT: Complete solution
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
handler.removeCallbacks(alarmTest);
}
public void triggerAlarm() {
handler.post(alarmTest,0); //wait 0 ms and run
}
Depending on your OS you may find making your thread volatile may fix this.
private volatile Thread thread;
However - there are better ways to do this. One very useful one is using a small (just one entry) BlockingQueue which is polled by the running thread.
// Use a BlockingQueue to signal the alarm to stop.
BlockingQueue<String> stop = new ArrayBlockingQueue<>(1);
public void stopAlarm() {
stop.add("Stop");
}
public void triggerAlarm() {
new Thread(() -> {
try {
while (stop.poll(1, TimeUnit.SECONDS) == null) {
// Stuff
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
Clearly you will have to manage edge cases like where someone calls stopAlarm when no alarm is running.

Java interrupting thread [duplicate]

I need a solution to properly stop the thread in Java.
I have IndexProcessorclass which implements the Runnable interface:
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
#Override
public void run() {
boolean run = true;
while (run) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
run = false;
}
}
}
}
And I have ServletContextListener class which starts and stops the thread:
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
#Override
public void contextInitialized(ServletContextEvent event) {
thread = new Thread(new IndexProcessor());
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
#Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (thread != null) {
thread.interrupt();
LOGGER.debug("Thread successfully stopped.");
}
}
}
But when I shutdown tomcat, I get the exception in my IndexProcessor class:
2012-06-09 17:04:50,671 [Thread-3] ERROR IndexProcessor Exception
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at lt.ccl.searchengine.processor.IndexProcessor.run(IndexProcessor.java:22)
at java.lang.Thread.run(Unknown Source)
I am using JDK 1.6. So the question is:
How can I stop the thread and not throw any exceptions?
P.S. I do not want to use .stop(); method because it is deprecated.
Using Thread.interrupt() is a perfectly acceptable way of doing this. In fact, it's probably preferrable to a flag as suggested above. The reason being that if you're in an interruptable blocking call (like Thread.sleep or using java.nio Channel operations), you'll actually be able to break out of those right away.
If you use a flag, you have to wait for the blocking operation to finish and then you can check your flag. In some cases you have to do this anyway, such as using standard InputStream/OutputStream which are not interruptable.
In that case, when a thread is interrupted, it will not interrupt the IO, however, you can easily do this routinely in your code (and you should do this at strategic points where you can safely stop and cleanup)
if (Thread.currentThread().isInterrupted()) {
// cleanup and stop execution
// for example a break in a loop
}
Like I said, the main advantage to Thread.interrupt() is that you can immediately break out of interruptable calls, which you can't do with the flag approach.
In the IndexProcessor class you need a way of setting a flag which informs the thread that it will need to terminate, similar to the variable run that you have used just in the class scope.
When you wish to stop the thread, you set this flag and call join() on the thread and wait for it to finish.
Make sure that the flag is thread safe by using a volatile variable or by using getter and setter methods which are synchronised with the variable being used as the flag.
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private volatile boolean running = true;
public void terminate() {
running = false;
}
#Override
public void run() {
while (running) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
running = false;
}
}
}
}
Then in SearchEngineContextListener:
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
private IndexProcessor runnable = null;
#Override
public void contextInitialized(ServletContextEvent event) {
runnable = new IndexProcessor();
thread = new Thread(runnable);
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
#Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (thread != null) {
runnable.terminate();
thread.join();
LOGGER.debug("Thread successfully stopped.");
}
}
}
Simple answer:
You can stop a thread INTERNALLY in one of two common ways:
The run method hits a return subroutine.
Run method finishes, and returns implicitly.
You can also stop threads EXTERNALLY:
Call system.exit (this kills your entire process)
Call the thread object's interrupt() method *
See if the thread has an implemented method that sounds like it would work (like kill() or stop())
*: The expectation is that this is supposed to stop a thread. However, what the thread actually does when this happens is entirely up to what the developer wrote when they created the thread implementation.
A common pattern you see with run method implementations is a while(boolean){}, where the boolean is typically something named isRunning, it's a member variable of its thread class, it's volatile, and typically accessible by other threads by a setter method of sorts, e.g. kill() { isRunnable=false; }. These subroutines are nice because they allow the thread to release any resources it holds before terminating.
You should always end threads by checking a flag in the run() loop (if any).
Your thread should look like this:
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private volatile boolean execute;
#Override
public void run() {
this.execute = true;
while (this.execute) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
this.execute = false;
}
}
}
public void stopExecuting() {
this.execute = false;
}
}
Then you can end the thread by calling thread.stopExecuting(). That way the thread is ended clean, but this takes up to 15 seconds (due to your sleep).
You can still call thread.interrupt() if it's really urgent - but the prefered way should always be checking the flag.
To avoid waiting for 15 seconds, you can split up the sleep like this:
...
try {
LOGGER.debug("Sleeping...");
for (int i = 0; (i < 150) && this.execute; i++) {
Thread.sleep((long) 100);
}
LOGGER.debug("Processing");
} catch (InterruptedException e) {
...
Typically, a thread is terminated when it's interrupted. So, why not use the native boolean? Try isInterrupted():
Thread t = new Thread(new Runnable(){
#Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
// do stuff
}
}});
t.start();
// Sleep a second, and then interrupt
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
t.interrupt();
ref- How can I kill a thread? without using stop();
For synchronizing threads I prefer using CountDownLatch which helps threads to wait until the process being performed complete. In this case, the worker class is set up with a CountDownLatch instance with a given count. A call to await method will block until the current count reaches zero due to invocations of the countDown method or the timeout set is reached. This approach allows interrupting a thread instantly without having to wait for the specified waiting time to elapse:
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private final CountDownLatch countdownlatch;
public IndexProcessor(CountDownLatch countdownlatch) {
this.countdownlatch = countdownlatch;
}
public void run() {
try {
while (!countdownlatch.await(15000, TimeUnit.MILLISECONDS)) {
LOGGER.debug("Processing...");
}
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
run = false;
}
}
}
When you want to finish execution of the other thread, execute countDown on the CountDownLatch and join the thread to the main thread:
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
private IndexProcessor runnable = null;
private CountDownLatch countdownLatch = null;
#Override
public void contextInitialized(ServletContextEvent event) {
countdownLatch = new CountDownLatch(1);
Thread thread = new Thread(new IndexProcessor(countdownLatch));
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
#Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (countdownLatch != null)
{
countdownLatch.countDown();
}
if (thread != null) {
try {
thread.join();
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
}
LOGGER.debug("Thread successfully stopped.");
}
}
}
Some supplementary info.
Both flag and interrupt are suggested in the Java doc.
https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
For a thread that waits for long periods (e.g., for input), use Thread.interrupt
public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}
I didn't get the interrupt to work in Android, so I used this method, works perfectly:
boolean shouldCheckUpdates = true;
private void startupCheckForUpdatesEveryFewSeconds() {
threadCheckChat = new Thread(new CheckUpdates());
threadCheckChat.start();
}
private class CheckUpdates implements Runnable{
public void run() {
while (shouldCheckUpdates){
System.out.println("Do your thing here");
}
}
}
public void stop(){
shouldCheckUpdates = false;
}
Brian Goetz in his book suggests to use Thread.currentThread().isInterrupted() flag and interrupt() method for cancellation.
Blocking library methods like sleep() and wait() try to detect when a thread has been interrupted and return early. They respond to interruption by clearing the interrupted status and throwing InterruptedException, indicating that the blocking operation completed early due to interruption.
The JVM makes no guarantees on how quickly a blocking method will detect interruption, but in practice this happens reasonably quickly.
class PrimeProducer extends Thread {
private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
public void run() {
try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted()) {
queue.put(p = p.nextProbablePrime()); // blocking operation
}
} catch (InterruptedException consumed) {
// allow thread to exit
}
// any code here will still be executed
}
public void cancel() {
interrupt();
}
}
If you put any code after catch block, it will still be executed as we swallow InterruptedException to exit from run() gracefully.
Just a couple words on how interrupt() works.
If interrupt is called on non-blocked thread, interrupt() will not cause InterruptedException inside run() but will just change flag isInterrupted to true and thread will continue its work until it reaches Thread.currentThread().isInterrupted() check and exit from run().
If interrupt is called on blocked thread (sleep() or wait()was called, in our case it's put() that might block a thread) then isInterrupted will be set to false and InterruptedException will be thrown inside put().

Java - Ideal use of wait and notify?

This code seems to work fine so far in testing. However I am new at multithreading and want to know if this code is ideal, since I know there is a lot of "donts" regarding concurrency.
Is there a better way to make an executor for queued Runnables on a single thread? This is my first time making one so I feel inclined to believe something could be better.
public class ExplosionExecutor{
private static List<Runnable> queue= new ArrayList<Runnable>();
private static Thread thread= new Thread(new Runnable() {
public void run() {
while(true){
Runnable[] queuedump;
synchronized (queue) {
if(queue.size()==0){
try {
queue.wait();
} catch (InterruptedException e){e.printStackTrace();}
}
queuedump= queue.toArray(new Runnable[0]);
queue.clear();
}
for(Runnable r : queuedump)
r.run();
}
}
}, "Nuke Explosions");
static{
thread.start();
}
public static void execute(Runnable command) {
synchronized (queue) {
queue.add(command);
queue.notify();
}
}
}
This is okay - ish.
It's best not to reinvent the wheel.
1) There are blocking queues which have methods to wait for new items and are already synchronized:
public static void main(String[] args) throws Exception {
final BlockingQueue<Runnable> r = new LinkedBlockingQueue<>();
final Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
r.take().run();
} catch (InterruptedException ex) {
return;
}
}
}
});
r.add(new Runnable() {
#Override
public void run() {
//do stuff
}
});
}
2) There is the ExecutorService API which encapsulates all this behaviour:
public static void main(String[] args) throws Exception {
final ExecutorService es = Executors.newSingleThreadExecutor();
es.execute(new Runnable() {
#Override
public void run() {
//do stuff
}
});
}
3) If you want to check the success of the submitted task and/or wait for a sumbitted task to finish you cannot do that using your API. With the ExecutorService you can do this very easily.
public static void main(String[] args) throws InterruptedException {
final ExecutorService es = Executors.newSingleThreadExecutor();
final Future<?> f = es.submit(new Runnable() {
#Override
public void run() {
//do stuff
}
});
try {
//wait
f.get();
} catch (ExecutionException ex) {
//there was an exeception in the task
}
}
A final note is that the way you have implemented your code there is no way to stop the consumer thread.
In my first example you would need to manually call t.interrupt() and because of my implementation this would case the thread to exit. In the second/third examples you would need to call ExecutorService.shutdown() to stop the consumer threads.
If you do not stop the threads then your program will not exit unless they are daemon.
Why are you making your own implementation? Java has a built-in ExecutorService that can run Runnables on a single thread http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html
//runs all Runnables in a single thread, one at a time
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.submit(runnable);
Here are few improvements... Of-course if you use BlockingQueue/ExecutorService we don't need to worry about synchronization/concurrency.
One main issue in the code is: "r.run()" instead of new Thread(r).start().
Use ConcurrentLinkedQueue data structure which is Thread safe.
You can offer to lock/notify on any static obj/class obj, need not be on the queue, as queue is already thread safe.
Queue to Array conversion is not needed. iterate for queue.poll().
Also you can also use concurrent locks API (ReentrantLock or Condition classes) instead of synchronized/wait/notify.
theexamtime.com

How to properly stop the Thread in Java?

I need a solution to properly stop the thread in Java.
I have IndexProcessorclass which implements the Runnable interface:
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
#Override
public void run() {
boolean run = true;
while (run) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
run = false;
}
}
}
}
And I have ServletContextListener class which starts and stops the thread:
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
#Override
public void contextInitialized(ServletContextEvent event) {
thread = new Thread(new IndexProcessor());
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
#Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (thread != null) {
thread.interrupt();
LOGGER.debug("Thread successfully stopped.");
}
}
}
But when I shutdown tomcat, I get the exception in my IndexProcessor class:
2012-06-09 17:04:50,671 [Thread-3] ERROR IndexProcessor Exception
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at lt.ccl.searchengine.processor.IndexProcessor.run(IndexProcessor.java:22)
at java.lang.Thread.run(Unknown Source)
I am using JDK 1.6. So the question is:
How can I stop the thread and not throw any exceptions?
P.S. I do not want to use .stop(); method because it is deprecated.
Using Thread.interrupt() is a perfectly acceptable way of doing this. In fact, it's probably preferrable to a flag as suggested above. The reason being that if you're in an interruptable blocking call (like Thread.sleep or using java.nio Channel operations), you'll actually be able to break out of those right away.
If you use a flag, you have to wait for the blocking operation to finish and then you can check your flag. In some cases you have to do this anyway, such as using standard InputStream/OutputStream which are not interruptable.
In that case, when a thread is interrupted, it will not interrupt the IO, however, you can easily do this routinely in your code (and you should do this at strategic points where you can safely stop and cleanup)
if (Thread.currentThread().isInterrupted()) {
// cleanup and stop execution
// for example a break in a loop
}
Like I said, the main advantage to Thread.interrupt() is that you can immediately break out of interruptable calls, which you can't do with the flag approach.
In the IndexProcessor class you need a way of setting a flag which informs the thread that it will need to terminate, similar to the variable run that you have used just in the class scope.
When you wish to stop the thread, you set this flag and call join() on the thread and wait for it to finish.
Make sure that the flag is thread safe by using a volatile variable or by using getter and setter methods which are synchronised with the variable being used as the flag.
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private volatile boolean running = true;
public void terminate() {
running = false;
}
#Override
public void run() {
while (running) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
running = false;
}
}
}
}
Then in SearchEngineContextListener:
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
private IndexProcessor runnable = null;
#Override
public void contextInitialized(ServletContextEvent event) {
runnable = new IndexProcessor();
thread = new Thread(runnable);
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
#Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (thread != null) {
runnable.terminate();
thread.join();
LOGGER.debug("Thread successfully stopped.");
}
}
}
Simple answer:
You can stop a thread INTERNALLY in one of two common ways:
The run method hits a return subroutine.
Run method finishes, and returns implicitly.
You can also stop threads EXTERNALLY:
Call system.exit (this kills your entire process)
Call the thread object's interrupt() method *
See if the thread has an implemented method that sounds like it would work (like kill() or stop())
*: The expectation is that this is supposed to stop a thread. However, what the thread actually does when this happens is entirely up to what the developer wrote when they created the thread implementation.
A common pattern you see with run method implementations is a while(boolean){}, where the boolean is typically something named isRunning, it's a member variable of its thread class, it's volatile, and typically accessible by other threads by a setter method of sorts, e.g. kill() { isRunnable=false; }. These subroutines are nice because they allow the thread to release any resources it holds before terminating.
You should always end threads by checking a flag in the run() loop (if any).
Your thread should look like this:
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private volatile boolean execute;
#Override
public void run() {
this.execute = true;
while (this.execute) {
try {
LOGGER.debug("Sleeping...");
Thread.sleep((long) 15000);
LOGGER.debug("Processing");
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
this.execute = false;
}
}
}
public void stopExecuting() {
this.execute = false;
}
}
Then you can end the thread by calling thread.stopExecuting(). That way the thread is ended clean, but this takes up to 15 seconds (due to your sleep).
You can still call thread.interrupt() if it's really urgent - but the prefered way should always be checking the flag.
To avoid waiting for 15 seconds, you can split up the sleep like this:
...
try {
LOGGER.debug("Sleeping...");
for (int i = 0; (i < 150) && this.execute; i++) {
Thread.sleep((long) 100);
}
LOGGER.debug("Processing");
} catch (InterruptedException e) {
...
Typically, a thread is terminated when it's interrupted. So, why not use the native boolean? Try isInterrupted():
Thread t = new Thread(new Runnable(){
#Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
// do stuff
}
}});
t.start();
// Sleep a second, and then interrupt
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
t.interrupt();
ref- How can I kill a thread? without using stop();
For synchronizing threads I prefer using CountDownLatch which helps threads to wait until the process being performed complete. In this case, the worker class is set up with a CountDownLatch instance with a given count. A call to await method will block until the current count reaches zero due to invocations of the countDown method or the timeout set is reached. This approach allows interrupting a thread instantly without having to wait for the specified waiting time to elapse:
public class IndexProcessor implements Runnable {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexProcessor.class);
private final CountDownLatch countdownlatch;
public IndexProcessor(CountDownLatch countdownlatch) {
this.countdownlatch = countdownlatch;
}
public void run() {
try {
while (!countdownlatch.await(15000, TimeUnit.MILLISECONDS)) {
LOGGER.debug("Processing...");
}
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
run = false;
}
}
}
When you want to finish execution of the other thread, execute countDown on the CountDownLatch and join the thread to the main thread:
public class SearchEngineContextListener implements ServletContextListener {
private static final Logger LOGGER = LoggerFactory.getLogger(SearchEngineContextListener.class);
private Thread thread = null;
private IndexProcessor runnable = null;
private CountDownLatch countdownLatch = null;
#Override
public void contextInitialized(ServletContextEvent event) {
countdownLatch = new CountDownLatch(1);
Thread thread = new Thread(new IndexProcessor(countdownLatch));
LOGGER.debug("Starting thread: " + thread);
thread.start();
LOGGER.debug("Background process successfully started.");
}
#Override
public void contextDestroyed(ServletContextEvent event) {
LOGGER.debug("Stopping thread: " + thread);
if (countdownLatch != null)
{
countdownLatch.countDown();
}
if (thread != null) {
try {
thread.join();
} catch (InterruptedException e) {
LOGGER.error("Exception", e);
}
LOGGER.debug("Thread successfully stopped.");
}
}
}
Some supplementary info.
Both flag and interrupt are suggested in the Java doc.
https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
private volatile Thread blinker;
public void stop() {
blinker = null;
}
public void run() {
Thread thisThread = Thread.currentThread();
while (blinker == thisThread) {
try {
Thread.sleep(interval);
} catch (InterruptedException e){
}
repaint();
}
}
For a thread that waits for long periods (e.g., for input), use Thread.interrupt
public void stop() {
Thread moribund = waiter;
waiter = null;
moribund.interrupt();
}
I didn't get the interrupt to work in Android, so I used this method, works perfectly:
boolean shouldCheckUpdates = true;
private void startupCheckForUpdatesEveryFewSeconds() {
threadCheckChat = new Thread(new CheckUpdates());
threadCheckChat.start();
}
private class CheckUpdates implements Runnable{
public void run() {
while (shouldCheckUpdates){
System.out.println("Do your thing here");
}
}
}
public void stop(){
shouldCheckUpdates = false;
}
Brian Goetz in his book suggests to use Thread.currentThread().isInterrupted() flag and interrupt() method for cancellation.
Blocking library methods like sleep() and wait() try to detect when a thread has been interrupted and return early. They respond to interruption by clearing the interrupted status and throwing InterruptedException, indicating that the blocking operation completed early due to interruption.
The JVM makes no guarantees on how quickly a blocking method will detect interruption, but in practice this happens reasonably quickly.
class PrimeProducer extends Thread {
private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
public void run() {
try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted()) {
queue.put(p = p.nextProbablePrime()); // blocking operation
}
} catch (InterruptedException consumed) {
// allow thread to exit
}
// any code here will still be executed
}
public void cancel() {
interrupt();
}
}
If you put any code after catch block, it will still be executed as we swallow InterruptedException to exit from run() gracefully.
Just a couple words on how interrupt() works.
If interrupt is called on non-blocked thread, interrupt() will not cause InterruptedException inside run() but will just change flag isInterrupted to true and thread will continue its work until it reaches Thread.currentThread().isInterrupted() check and exit from run().
If interrupt is called on blocked thread (sleep() or wait()was called, in our case it's put() that might block a thread) then isInterrupted will be set to false and InterruptedException will be thrown inside put().

Categories

Resources