I am confused with concurrency - i am trying to stop the consumer thread from running if the producer is shutdown but am having issues if the consumer is blocked on take(). I have tried adding a posion pill, interruptung the current thread, using a boolean flag and still to no avail.
Please can someone help advise where I am going wrong. Thanks.
public class TestPoisonPill implements Runnable {
private BlockingQueue<String> queue = new ArrayBlockingQueue<String>(1);
private volatile boolean stopped = false;
public void addToQueue(String event) throws InterruptedException{
System.out.println("in add to queue");
if(event != null){
try {
queue.put(event);
} catch (InterruptedException e) {
stopped = true;
queue.put("Poison");
System.out.println("Unable to add the event to the queue, order routing processing is stopped");
throw e;
}
}
}
#Override
public void run() {
while(!stopped){
try {
if(queue.size() > 0){
String string = queue.take();
System.out.println("taken " + string + "from the queue");
}else{
continue;
}
}
catch (InterruptedException e) {
stopped = true;
}
}
}
public boolean isStopped(){
return stopped;
}
protected BlockingQueue<String> getQueue() {
return queue;
}
protected void setBoolean(boolean b){
this.stopped = b;
}
public static void main(String[] args) throws InterruptedException{
ExecutorService exec = Executors.newSingleThreadExecutor();
final TestPoisonPill t = new TestPoisonPill();
exec.execute(t);
ExecutorService exec2 = Executors.newSingleThreadExecutor();
Runnable addTask = new Runnable() {
public void run() {
while (true) {
try {
t.addToQueue("hi");
Thread.sleep(100);
} catch (InterruptedException ex) {
System.out.println("add task interrupted ");
t.setBoolean(true);
break;
}
}
}
};
exec2.execute(addTask);
Thread.sleep(1000);
exec2.shutdownNow();
}
}
am confused with concurrency - i am trying to stop the consumer thread from running if the producer is shutdown but am having issues if the consumer is blocked on take()
If you problem is that you program is not stopping, I think you are missing an exec.shutdownNow() on your first ExecutorService. This will interrupt your first thread, if you change your loop to be something like:
while (!stopped && !Thread.currentThread().isInterrupted()) {
Without the interrupt flag check any interrupt will be not been seen by the thread. An interrupt is just a flag that is set on the thread. Certain methods (like Thread.sleep(...) and BlockingQueue.take()) throw InterruptedException when a thread is interrupted but your consumer is spinning and never calling take().
Really, the spin loop in the consumer is an extremely bad pattern. It should just call queue.take() and then either use the interrupt or have your producer actually submit a poisoned pill. Something like:
while (!Thread.currentThread().isInterrupted()) {
String string;
try {
string = queue.take();
} catch (InterruptedException e) {
break;
}
// here is where you could check for a poison pill
// something like: if (string == STOP_PILL) break;
System.out.println("taken " + string + "from the queue");
}
You don't really need the stopped flag if you are using interrupt appropriately.
You mention having tried a "poisoned pill". For others, a poisoned pill is when you put a specific "special" object on the queue which the consumer uses to know when to shutdown. Something like the following should work:
private static final String STOP_PILL = "__STOP_PLEASE!!__";
...
// the consumer removes from the queue
String string = queue.take();
// it tests to see if it a pill, == is better than .equals here
if (string == STOP_PILL) {
// the consumer should stop
break;
}
...
// to stop the consumer, the producer puts the pill into the queue
queue.put(STOP_PILL);
Lastly, you are using 2 ExecutorService instances when you could easily use one. I guess the point here is to interrupt only one of them but FYI. You can use a single Executors.newCachedThreadPool() which will create the number of threads you need.
You never shutdown your exec executor, only exec2, so the thread running your TestPoisonPill never gets interrupted.
Related
I have the code below:
#Override
public boolean start() {
boolean b = false;
if (status != RUNNING) {
LOGGER.info("Starting Auto Rescheduler Process...");
try {
b = super.start();
final ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Rescheduler-Pool-%d").build();
ExecutorService exServ = Executors.newSingleThreadExecutor(threadFactory);
service = MoreExecutors.listeningDecorator(exServ);
} catch (Exception e) {
LOGGER.error("Error starting Auto Rescheduler Process! {}", e.getMessage());
LOGGER.debug("{}", e);
b = false;
}
} else {
LOGGER.info("Asked to start Auto Rescheduler Process but it had already started. Ignoring...");
}
return b;
}
The AutoRescheduler is the runnable below:
private class AutoScheduler implements Runnable {
private static final String DEFAULT_CONFIGURABLE_MINUTES_VALUE = "other";
private static final long DEFAULT_DELAY_MINUTES = 60L;
#Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
//BLOCKS HERE UNTIL A FINISHED EVENT IS PUT IN QUEUE
final FinishedEvent fEvent = finishedEventsQueue.take();
LOGGER.info("Received a finished Event for {} and I am going to reschedule it", fEvent);
final MyTask task = fEvent.getSource();
final LocalDateTime nextRunTime = caclulcateNextRightTime(task);
boolean b = scheduleEventService.scheduleEventANew(task, nextRunTime);
if (b) {
cronController.loadSchedule();
LOGGER.info("Rescheduled event {} for {}", task, nextRunTime);
}
} catch (InterruptedException e) {
LOGGER.error("Interrupted while waiting for a new finishedEventQueue");
Thread.currentThread().interrupt();
}
}
I see events being caught and put in the queue. Normally I then see them being rescheduled by the AutoReschduler
However from time to time I stop seeing them being rescheduled which leads me to believe that the reschedulingThread dies silently. After this happens no more events are taken from the queue until I restart the process (I have a GUI that allows me to call the stop() and start() methods of the public class). After I restart it though, the blocked events are rescheduled normally which means that they are in the queue indeed.
Does anyone have an idea?
EDIT
I have reproduced the error in Eclipse. The thread does not die (I have tested with the ExecutorService as well. However take() still does not take the item from the queue although it is placed there.
I have a method to run that makes connection to server, and when server fails, would wait until it receives a message that server is up again. However, this entire method should have a timeout, and if it is over the time, method should interrupt and return error log instead.
private Semaphore sem = new Semaphore(0);
private TimeUnit unit = TimeUnit.MILLISECONDS;
public String some_method(Object params, long timeout, TimeUnit unit) {
long time = 0;
while(time < timeout) { // not sure about timeout method
try {
//some task that is prone to ServerConnectException
return; // returns value and exits
} catch(ServerConnectException ex) {
sem.acquire();
} catch(InterruptedException uhoh) {
System.out.println("uhoh, thread interrupted");
}
// increment time somehow
}
sem.release();
return null; // a message of task incompletion
}
I was thinking about running a thread containing semaphore that blocks thread if there's a server failure problem, but I cannot seem to organize thread such that it will contain the semaphore but be contained by method itself.
QUESTION:
- However, the method is already in a gigantic class and making separate Thread for just that method will mess up entire call hierarchy as well as whole API, so I don't want to do that. I need some process that runs along with the some_method and places lock and release on its processes as needed, with timeout. What should I be thinking? Some other concurrency wrapper like executor?
Thanks!
Semaphore doesn't seem to be the right concurrency primitive to use here, as you don't really need a utility for locking, but rather a utility to help you coordinate inter-thread communication.
If you need to communicate a stream of values, you would typically use a blocking queue, but if you need to communicate a single value, a CountDownLatch and a variable do the trick. For example (untested):
public String requestWithRetry(final Object params, long timeout, TimeUnit unit) throws InterruptedException {
String[] result = new String[1];
CountDownLatch latch = new CountDownLatch(1);
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
result[0] = request(params);
latch.countDown();
return;
}
catch(OtherException oe) {
// ignore and retry
}
catch(InterruptedException ie) {
// task was cancelled; terminate thread
return;
}
}
}
});
t.start();
try {
if (!latch.await(timeout, unit)) {
t.interrupt(); // cancel the background task if timed out
}
// note that this returns null if timed out
return result[0];
}
catch(InterruptedException ie) {
t.interrupt(); // cancel the background task
throw ie;
}
}
private String request(Object params) throws OtherException, InterruptedException {
// should handle interruption to cancel this operation
return null;
}
i want to pause thread which is writing messages in file by iterate message list. When message list is empty i want thread to stop and thread is resumed when message in a list.
I know stop,suspend (),resume methods is deprecated but if thread is continuously in background it consumes cpu. I did lots of googling but can't find proper answer. please any one help me out
Here is my code:
private Thread mFileWriterThread = new Thread() {
#Override
public synchronized void run() {
while (mIsRunning) {
synchronized (mMessageList) {
Iterator it = mMessageList.iterator();
while ((it.hasNext())) {
String message = (String) it.next();
writeToFile(fileOutputStream, message);
mMessageList.remove(message);
}
}
}
}
};
That's what a BlockingQueue exists for. It has a take() method that forces a thread to block until an Object is avalaible. Your problem can be solved with a simple producer-consumer design.
I'm pasting here a minimal snippet taken from the Oracle examples:
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
Of course Consumer an Producer have to share the queue somehow (just passing it to the constructor as shown in the example will work fine).
You want to use wait() to make the thread block*. And then call notify() to wake up the thread again. Google for "java wait notify" will give you a tutorial.
*Block here mean wait without using any resources, until an other thread wake it up.
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'm running Java 1.5 on Solaris 10.
My program is a standalone java program, using java concurrency package and log4j-1.2.12.jar to log certain information. primary logic is as below
ExecutorService executor = new AppThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(Integer.MAX_VALUE), new AppThreadFactory("BSRT", true), new ThreadPoolExecutor.CallerRunsPolicy());
CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(executor);
for (final Integer id : taskList) {
Callable<Integer> c = new Callable<Integer>() {
public Integer call() throws Exception {
int newId = DB operation(id);
return newId;
}
};
completionService.submit(c);
}
logger.debug("Start retrievie result");
for (Integer id : taskList) {
try {
Future<Integer> future = completionService.poll(1, TimeUnit.SECONDS);
Integer taskId=null;
if (future != null) {
logger.debug("future is obtained.");
taskId = future.get();
} else {
logger.error("wait too long and get nothing!");
break;
}
if (taskId != null) {
taskIdList.add(taskId);
}
} catch (ExecutionException ignore) {
// log the cause and ignore this aborted task,coninue with
// next available task.
logger.warn(ignore.getCause());
} catch (InterruptedException e) {
logger.warn("interrupted...");
// Re-assert the thread’s interrupted status
Thread.currentThread().interrupt();
}
}executor.shutdown();
During the execution of my program, Sometimes (not always) I'm getting this error ...
executor.shutdown();
will not be able to interrupt AppThread after return from the call super.run();
because the woker is already removed from workers set used internally by ThreadPoolExecutor, executor does not have reference to AppThread from that point of time.
btw: the log file is accessible and size is big enough.
log4j:ERROR Failed to flush writer,
java.io.InterruptedIOException
at java.io.FileOutputStream.writeBytes(Native Method)
at java.io.FileOutputStream.write(FileOutputStream.java:260)
at sun.nio.cs.StreamEncoder$CharsetSE.writeBytes(StreamEncoder.java:336)
at sun.nio.cs.StreamEncoder$CharsetSE.implFlushBuffer(StreamEncoder.java:404)
at sun.nio.cs.StreamEncoder$CharsetSE.implFlush(StreamEncoder.java:408)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:152)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:213)
at org.apache.log4j.helpers.QuietWriter.flush(QuietWriter.java:57)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:315)
at org.apache.log4j.DailyRollingFileAppender.subAppend(DailyRollingFileAppender.java:358)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:159)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:230)
at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:65)
at org.apache.log4j.Category.callAppenders(Category.java:203)
at org.apache.log4j.Category.forcedLog(Category.java:388)
at org.apache.log4j.Category.debug(Category.java:257)
at AppThread.run( AppThread.java: 33)
33 is the line: if (debug)
logger.info("Exiting " + getName());
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.log4j.Logger;
public class AppThread extends Thread {
public static final String DEFAULT_NAME = "MyAppThread";
private static volatile boolean debugLifecycle = false;
private static final AtomicInteger created = new AtomicInteger();
private static final AtomicInteger alive = new AtomicInteger();
private static final Logger logger = Logger.getLogger(AppThread.class);
private boolean dump = false;
public AppThread(Runnable r) {
this(r, DEFAULT_NAME);
}
public AppThread(Runnable runnable, String name) {
super(runnable, name + "-" + created.incrementAndGet());
logger.debug(name + "'s constructor running");
}
public void interrupt() {
if (!dump) {
super.interrupt();
}
if (dump) {
logger.debug("interrupt : " + getName() + " <<<");
Thread.dumpStack();
logger.debug("interrupt : " + getName() + " >>>");
}
}
public void run() {
boolean debug = debugLifecycle;
if (debug)
logger.info("Created " + getName());
try {
alive.incrementAndGet();
super.run();
logger.debug("running!");
} finally {
alive.decrementAndGet();
dump = true;
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
logger.debug(e);
}
if (debug)
logger.info("Exiting " + getName());
}
}
public static int getThreadsCreated() {
return created.get();
}
public static int getThreadsAlive() {
return alive.get();
}
public static boolean getDebug() {
return debugLifecycle;
}
public static void setDebug(boolean b) {
debugLifecycle = b;
}
}
Another problem is that in order to debug the cause of java.io.InterruptedIOException , I added
try {
Thread.sleep(100000);
} catch (InterruptedException e) {
logger.debug(e);
}
in finally clause in the run method for AppThread. when InterruptedException is catched in the finally clause, the override interrupt() method is never called. so who interrupt AppThread? is the same guy cause java.io.InterruptedIOException?
Yes:
shutdownNow
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.
JavaDoc.
Simply use shutdown() instead of shutdownNow(). When you are forcibly calling shutdownNow() this is what you should expect - JVM gracefully interrupts I/O and shuts down the thread as fast as possible.
However I would make sure that logging isn't the bottleneck in your application. Simply make few thread dumps during the execution of your program and see how often threads are writing or waiting for I/O. Poor man's profiling.
Interrupting the worker threads is actually a feature of the Executor framework to allow worker threads to gracefully shut down when asked to do so through interrupt(). It's documented behavior for shutdownNow().
If you don't want this, call shutdown() -- it won't interrupt() your worker threads, the Executor will just stop accepting new tasks.
I have similar problems.
My research went so far that Thread.interrupt() sets the interrupt flag. This leads to an interrupted IO operation deep in the Java Stack. But the IO methods are typically not declared to throw an InterruptedException.
Instead an InterruptedIOException is thrown and the interrupted state of the Thread is cleared!. If you wrote a Worker that expects (catches) IOExceptions, you have to catch the InterruptedIOException separately and call Thead.currentThread().interrupt() in the catch clause.