I have deployed java service application on linux using apache jsvc. It's a multithread application, however when daemon stop is initiated, it kills jvm before all threads are finished.
It goes like this:
WorkerLauncher which implements daemon interface, starts service
WorkerPool class initiates parent thread and worker (child) threads that are represented by Worker class.
When WorkerLauncher stop is called, WorkerPool thread is interrupt and this InterruptedException is caught, where child threads are interrupted as well.
When child thread is interrupted, it performs calculations before stopping. This is where it goes wrong: calculations are not finished before thread is killed I guess (not quite sure here).
WorkerLauncher
public class WorkerLauncher implements Daemon {
private static final Logger log = LoggerFactory.getLogger("com.worker");
private WorkerPool pool;
#Override
public void init(DaemonContext context) {
}
#Override
public void start() {
log.info("Starting worker pool...");
if (pool == null) pool = new WorkerPool();
pool.start();
log.info("Worker pool started");
}
#Override
public void stop(){
pool.stop();
}
#Override
public void destroy() {
pool = null;
}
}
WorkerPool
public class WorkerPool implements Runnable {
private static final Logger log = LoggerFactory.getLogger("com.worker");
private Thread thread = null;
private List<Thread> workers = new ArrayList<Thread>();
public WorkerPool() {
for (int i = 0; i < 1; i++) workers.add(new Thread(new Worker("Worker "+i), "Worker "+i));
this.thread = new Thread(this, "Worker Main");
}
#Override
public void run() {
for (Thread thread : workers) {
thread.start();
}
while (isRunning()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
log.info("Worker pool stopping");
for (Thread worker : workers) {
worker.interrupt();
}
break;
}
}
}
public boolean isRunning() {
return !thread.isInterrupted();
}
public void stop() {
thread.interrupt();
}
public void start() {
thread.start();
}
}
Worker
public class Worker implements Runnable{
private static final Logger log = LoggerFactory.getLogger("com.worker");
private String name;
public Worker(String name) {
this.name = name;
}
private void stop() {
longCalculations();
log.info("Worker {] stopped", name);
}
#Override
public void run() {
try {
try {
while (true) {
Thread.sleep(1000);
}
} catch (InterruptedException e) {
log.info("InterruptedException");
}
} finally {
stop();
}
}
private void longCalculations() {
for (int i = 0; i < 99999; i++) {
for (int j = 0; j < 9999; j++) {
Math.round(i + j * 0.999);
}
}
}
}
This is just an example from real application, but with this I reproduce the same issue. commons-daemon 1.1 and 1.2 versions tested. If long calculations are removed or made to last shorter (better performance) everything works. What am I missing here? Any ideas?
Here's how log output looks like:
07:55:10.790 ( main) INFO Starting worker pool...
07:55:10.791 ( main) INFO Worker pool started
07:55:34.056 (Worker Main) INFO Worker pool stopping
07:55:34.057 ( Worker 0) INFO InterruptedException
Note how Worker {] stopped is missing. And in real application 3rd party process that was started by worker is still running, which can be seen in ps -A even if jsvc does not show in processes.
EDIT
Modified stop() method:
private void stop() {
log.info("Worker {] being stopped", name);
longCalculations();
log.info("Worker {] stopped", name);
}
Log output:
06:18:55.762 ( main) INFO Starting worker pool...
06:18:55.764 ( main) INFO Worker pool started
06:19:08.614 (Worker Main) INFO Worker pool stopping
06:19:08.615 ( Worker 0) INFO InterruptedException
06:19:08.616 ( Worker 0) INFO Worker {] being stopped
I start/stop the service using jsvc:
START
./jsvc -cwd . -cp commons-daemon-1.1.0.jar:multithread-test.jar -outfile /tmp/worker.out -errfile /tmp/worker.err -pidfile /var/run/worker.pid com.worker.WorkerLauncher
STOP
./jsvc -cwd . -cp commons-daemon-1.1.0.jar:multithread-test.jar -outfile /tmp/worker.out -errfile /tmp/worker.err -pidfile /var/run/worker.pid -stop com.worker.WorkerLauncher
IMPORTANT!
Forgot to mention, that this application works as expected on windows using apache procun. This is only happening when lauching it on linux using jsvc.
ANOTHER EDIT
if I wait for threads to finish (check if any worker thread isAlive) after pool.stop() in WorkerLauncher.stop() everything works.
#Override
public void stop(){
pool.stop();
while(pool.isAnyGuardianRunning()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
}
And in WorkerPool:
public boolean isAnyGuardianRunning() {
for (Thread thread : workers) {
if (thread.isAlive()) return true;
}
return false;
}
But I still don't know why is this happening... Any ideas?
Related
I have made a class called AbortableThread that is supposed to start and stop a thread when I want to. The class is relatively small since it just contains this code :
public class AbortableThread implements Runnable
{
private Thread worker;
private Runnable target;
public AbortableThread(Runnable target)
{
this.target = target;
}
public void start()
{
worker = new Thread(this);
worker.start();
}
public void stop()
{
worker.interrupt();
}
public void run()
{
while (!worker.isInterrupted())
target.run();
}
}
However, calling stop() does not stop the Thread. I think that's because target.run() runs on a separate thread, but I have no clue.
There isn’t a good way to stop a Runnable from outside (as a last resort there is stop, but that isn’t a good way).
A Runnable needs to be a good citizen and check for interruption itself, using Thread.currentThread().isInterrupted().
If the Runnable catches InterruptedException, the interrupt flag will be cleared; the Runnable needs to restore the interrupt flag by calling interrupt on the current thread.
In the posted code what happens is that the Runnable executes on the worker thread and the worker never gets a chance to check the interruption flag until the Runnable completes. Assuming the Runnable is something like
() -> { try {
Thread.sleep(100000L):
} catch (InterruptedException e) {}}
then the sleep would be cut short when the worker is interrupted, but the interrupt flag would be cleared so the Runnable would be executed again in the next iteration of the loop.
Try something like this:
public class AbortableThread implements Runnable
{
private final AtomicBoolean running = new AtomicBoolean(false);
private Thread worker;
private Runnable target;
public AbortableThread(Runnable target)
{
this.target = target;
}
public void start()
{
worker = new Thread(this);
worker.start();
}
public void stop()
{
running.set(false);
}
public void run()
{
running.set(true);
while (running.get()) {
try {
// make an small sleep
Thread.sleep(1);
} catch (InterruptedException e){
Thread.currentThread().interrupt();
System.out.println(
"Thread was interrupted, Failed to complete operation");
}
// do something here like the one in question; it must be none-blocking
target.run();
}
}
}
A complete example can be found here:
How to Kill a Java Thread
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().
Is there a way I can do a similar task like the android OS or java AWT thread where a task is run on a particular thread regardless of which thread of which thread the method was called from e.g. repaint().
private Thread thread;
public void startThread(){ //method which start's my thread
thread = new Thread(new Runnable(){
doSomething();
});
thread.start()
}
public void submitTask(Runnable runnable){
//run the runnable task on the thread "thread"
}
How can I achieve something like this, on a situation where I have more then one active thread
How I've dealt with this scenario before is to create a work queue and a thread which processes tasks that get added to it. So any thread can add a work item to the queue and the same thread will process it regardless of what thread added the work item.
public class MyClass {
private LinkedBlockingQueue<MyTask> myTaskProcessingQueue;
public MyClass() {
myTaskProcessingQueue = new LinkedBlockingQueue<MyTask>();
new MyTaskWorker().start();
}
public void processTask(MyTask myTask) {
myTaskProcessingQueue.put(myTask);
}
private class MyTaskWorker extends Thread {
#Override
public void run() {
while (true) {
try {
processMyTask(myTaskProcessingQueue.take());
} catch (InterruptedException ie) {
// handle it
}
}
}
private void processMyTask(MyTask myTask) {
// do work
}
}
}
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().
I am writing a multithreaded program in which i am getting exception java.lang.IllegalThreadStateException.
Any help would be welcomed
here is my stack trace
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
at GeoMain.main(GeoMain.java:18)
here is my code for main class
public class TMain {
public static void main(String[] args) {
String Batchid="1,2,3";
String batch[]=StringUtils.split(Batchid,",");
MultiThread gt=new MultiThread();
for(int i=0;i<batch.length;i++){
gt.setBatch(batch[i]);
gt.start();
System.out.println("Thread started for "+batch[i]);
}
System.out.println("mainfinish");
}
}
and hereis my multi thread class
public class MultiThread extends Thread {
private static Queue<String> queue = new LinkedList<String>();
private static Boolean isInUse = false;
private void runcoder()
{
String batchid=null;
BatchIdCreator bid=null;
while(isInUse)
{
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
System.out.println("exception");
e.printStackTrace();
}
}
isInUse=true;
synchronized(isInUse)
{
isInUse=true;
batchid=queue.poll();
System.out.println(batchid);
System.out.println(batchid);
bid=new BatchIdCreator(batchid);
// get a list from database
bid.getList();
// print on console
bid.printList();
isInUse=false;
}
}
#Override
public void run() {
runcoder();
}
public void setBatch(String batchid)
{
queue.add(batchid);
}
public static Boolean getIsInUse() {
return isInUse;
}
}
In this snippet:
MultiThread gt=new MultiThread();
for(int i=0;i<batch.length;i++){
gt.setBatch(batch[i]);
gt.start(); <--- Same thread object as in previous iteration
System.out.println("Thread started for "+batch[i]);
}
you're calling start() over and over again on the same thread. As described in the documentation, this is illegal:
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
You may want to move the new MultiThread() into the loop to avoid this:
----------.
for(int i=0;i<batch.length;i++){ |
|
MultiThread gt=new MultiThread(); <--'
gt.setBatch(batch[i]);
gt.start();
System.out.println("Thread started for "+batch[i]);
}
You cannot start the same thread twice. You you want to create several threads move the creation of thread instance into the loop:
for(int i=0;i<batch.length;i++){
MultiThread gt=new MultiThread();
gt.setBatch(batch[i]);
gt.start();
System.out.println("Thread started for "+batch[i]);
}
You are attempting to start the same (Multi)Thread instance multiple times. Create a new instance of Multithread inside the loop, so each thread gets its own instance.