I have a service, and I would like it to have the following behavior:
If service receives InterruptedException, or JVM shuts down, it should try to stop gracefully
If there's some "catastrophic" event, the service should just quit
Any other exception should be logged, state should reset, and loop should keep running
Loop should not quit under any other circumstance.
So here's a overly simplified version of what I came up with.
On class level:
private static volatile boolean keepRunning = true;
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
keepRunning = false;
}
});
}
And then the loop:
while(keepRunning) {
try {
// Do something useful
Thread.sleep(10000); // just an example of something that can cause InterruptedException
}
catch(InterruptedException e) {
keepRunning = false;
}
catch(Exception e) { // catches all exceptions, but not any errors
// log it
// reset state
}
}
if(!keepRunning) {
// shut down gracefully
}
It seems satisfies all 4 conditions, but there are some problems and unclear parts:
(problem) Catching Exception and not doing anything is against all good practices. But is it acceptable in this case, or there's a better solution?
(question) Is not catching Error all I need to do to satisfy condition #2? Or are there other situations I should be aware of?
(unclear) Usually it's recommended that the "shut down gracefully" code goes into finally section after exception, and I don't really like that I have to check it after loop (if(!keepRunning)). But it seems doesn't fit in finally in this case. Is there a better way to do that?
(question) This code is written for Java 7. Would anything be changed/improved with Java 8?
I will appreciate either direct answers to my questions, or pointers to different patterns/solutions. Thanks in advance.
It is ok to catch the Exception in your case.
Not catching Error is a good practice if you run tests.
The finally block is what you should use to shut down gracefully and yes - the if statement in the finally block is needed and generally ok.
If an error occurs, your finally block will still execute so it is all good.
This code is ok for both Java 7 and Java 8
Related
As the title suggested, I have some code wrapped in a while(true) infinite loop, and all of them are fully caught by try and catch block. This thread is started in the main method, however, after long run, this worker thread is vanished mysteriously when I check using the jstack and causing work accumulated.
Below is my code:
public void run() {
while (true) {
try {
// Consumer consumes from Kafka server
Global.KAFKA_METRIC_DATA_CONSUMER.consume(topic, handler);
} catch (Exception e) {
logger.error("Kafka consumer process was interrupted by exception!");
} finally {
try {
// Prevent restart too often
Thread.sleep(30 * BaseConst.SECOND);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
For my understanding, this structure will keep the thread running so is the consumer. Even if the consume() methods failed, it will restart infinitely. However, as I mentioned above, the whole thread disappear silently without any error log. Could anyone provide some clue please?
Some more information that might be helpful:
I have checked the consume method will never shutdown the consumer
nor close the socket to the server. It will continuously try to
connect server after fail.
I analysed the java heap dump, and I found there is a memory leak
somewhere else in the project, causing memory occupation extremely
high and the gc very often. However, the main method is still
running.
OutOfMemoryError is not an Exception. It's an Error derived from Throwable.
If that was thrown somewhere in your consume(topic, handler), finally would still be called, delaying the inevitable some 30s... but after that the error would be passed upward and your loop would be terminated.
You are catching Exception so there's a chance that a java.lang.Error or a java.lang.Throwable is being thrown (eg OutOfMemoryError)
If you really want to catch everything, you'll need to catch Throwable and not just Exception subclasses.
Your thread is probably killed by an error.
An error is not an exception! But they both extend Throwable
Add another catch block that catches errors.
Throwable should never be caught, because errors require a different handling than exceptions
We're calling "lock()" on a ReentrantLock and threads are getting stuck there when they apparently shouldn't.
When debugging with a breakpoint just before the call to "lock()", the first thread would stop there with the program pointer going to "Thread.exit()".
The lock object's toString() says "unlocked" and it's "state" attribute is "0".
The behavior is not always the same. Sometimes the first thread goes past the lock as expected.
userLock.lock(); //first thread sometimes gets stuck here (and the following ones as well)
//"userLock" has "state=0" and toString() says "UNLOCKED"
try {
Transaction tr = HibernateConfig.getSessionFactory().getCurrentSession().beginTransaction();
try {
execute();
tr.commit();
} catch (ConstraintViolationException e) {
//probably traces with repeated time
System.err.println(e.getMessage());
if (tr.isActive()) {
tr.rollback();
}
} catch (RuntimeException e) {
e.printStackTrace();
if (tr.isActive()) {
tr.rollback();
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
userLock.unlock();
}
try to put a breakpoint after userLock.lock(); then you should get the thread, that gets the lock.
alternatively you could use userLock.getOwner(); right behind .lock() to see wich thread got the lock.
The problem was my breakpoint was not before "lock()" like I said, but on it.
What happened is a bunch of threads would be blocked in that line by the breakpoint, one of them would still acquire the lock, and then the debugger would give me control over a random one of them which hadn't acquired the lock. And I was failing to check every thread blocked by the breakpoint to find the free one.
In the end I put the breakpoint actually before the lock and it behaved as expected.
This was confusing and I hope the question will still help someone.
Note: I'm still confused by the fact the lock's state said "unlocked" in the debugger while I was controlling a locked thread.
I'm developing a multithreaded application to make connections to external servers - each on separate threads - and will be blocked until there is input. Each of these extends the Thread class. For the sake of explanation, let's call these "connection threads".
All these connection threads are stored in a concurrent hashmap.
Then, I allow RESTful web services method call to cancel any of the threads. (I'm using Grizzly/Jersey, so each call is a thread on its own.)
I retrieve the specific connection thread (from the hashmap) and call the interrupt() method on it.
So, here is the question, within the connection thread, how do I catch the InterruptedException? (I'd like to do something when the connection thread is stopped by an external RESTful command.)
So, here is the question, within the connection thread, how do I catch
the InterruptedException?
You can not. Since if your thread is blocked on a read I/O operation it can not be interrupted. This is because the interrupt just sets a flag to indicate that the thread has been interrupted. But if your thread has been blocked for I/O it will not see the flag.
The proper way for this is to close the underlying socket (that the thread is blocked to), then catch the exception and propagate it up.
So since your connection threads extend Thread do the following:
#Override
public void interrupt(){
try{
socket.close();
}
finally{
super.interrupt();
}
}
This way it is possible to interrupt a thread blocked on the I/O.
Then in your run method do:
#Override
public void run(){
while(!Thread.currentThread().isInterrupted()){
//Do your work
}
}
So in your case don't try to catch an InterruptedException. You can not interrupt the thread blocked on I/O. Just check if your thread has been interrupted and facilitate the interruption by closing the stream.
When you call Thread.interrupt() on some thread, what happens is that 'interruption' flag is set for that thread. Some methods do check this flag (by Thread.interrupted() or Thread.isInterrupted()) and throw InterruptedException, but usually only methods that can block do that. So there is no guarantee that InterruptedException will ever be thrown in interrupted thread. If you don't call any method that throws InterruptedException, there is no point in catching that exception, since it will not be thrown at all. However you can always check if your thread was interrupted by calling Thread.isInterrupted().
the problem it is with blocking.
Hoverer, try this code, maybe it will help you:
try{
yourObject.read();
}catch(InterruptedException ie){
// interrupted by other thread
}
catch(Exception ex){
// io or some other exception happent
}
your read method, should check if there is available buytes at socket for eg, if there are than read it, othervise go to speel mode. When is sleeping than is available the wake up (InterruptedException) at pur socket read ( whatever read have you) it will be blocked. Some API has a value to max waiting, eg 5 sec 60 sec, if nothing o read than it will be next code executed.
class MyReadingObject
{
public read() throws InterruptedException{
while(shouldIread){
if(socket.available() > 0){
byte[] buff = new byte[socket.avaialble()]
socket.read(buff);
return;
}
else{
Thread.currentThread.sleep(whateverMilliseconds);
}
}
}
}
something like that, but with error handling and some design patterns
Calling interrupt() on a thread doesn't stop it, it just switches on the interrupt flag. It's the responsibility of the code to handle the change in the interrupt status of the thread in consideration and act accordingly. If you are performing a blocking operation in that thread, you are pretty much SOL because your thread is "blocking" on the read. Have a look at the answer which I posted here. So basically, unless you are looping over stuff or periodically checking some flags inside that thread, you have no way of breaking out without closing sockets or stuff like that.
One solution here is to "explicitly" expose the underlying connection object and call close() on it, forcing it to throw some sort of exception, which can be then handled in the threaded code. Something like:
class MyAction extends Thread implements Disposable {
public void doStuff() {
try {
byte[] data = this.connection.readFully();
} catch (InterruptedException e) {
// possibly interrupted by forceful connection close
}
#Override
public void dispose() {
this.connection.close();
}
}
// Elsewhere in code
MyAction action = conMap.get("something");
action.dispose();
Use a try-catch like so:
try {
//code
} catch ( InterruptedException e) {
//interrupted
}
I think that should do the trick, you could also keep a boolean variable on whether to exit, so they would check that variable, if it's true, stop
Sometimes, you just have to catch Throwable, e.g. when writing a dispatcher queue that dispatches generic items and needs to recover from any errors (said dispatcher logs all caught exceptions, but silently, and then execution is continued on other items).
One best practice I can think of is to always rethrow the exception if it's InterruptedException, because this means someone interrupted my thread and wants to kill it.
Another suggestion (that came from a comment, not an answer) is to always rethrow ThreadDeath
Any other best practices?
Probably the most important one is, never swallow a checked exception. By this I mean don't do this:
try {
...
} catch (IOException e) {
}
unless that's what you intend. Sometimes people swallow checked exceptions because they don't know what to do with them or don't want to (or can't) pollute their interface with "throws Exception" clauses.
If you don't know what to do with it, do this:
try {
...
} catch (IOException e) {
throw new RuntimeException(e);
}
The other one that springs to mind is to make sure you deal with exceptions. Reading a file should look something like this:
FileInputStream in = null;
try {
in = new FileInputStream(new File("..."));;
// do stuff
} catch (IOException e) {
// deal with it appropriately
} finally {
if (in != null) try { in.close(); } catch (IOException e) { /* swallow this one */ }
}
Depends on what you are working on.
if you are developing an API to be used by some one else, its better to re-throw the Exception or wrap it into a custom exception of yours and throw.
Whereas if you are developing an enduser application you need to handle this exception and do the needful.
What about OutOfMemoryError (or perhaps its super class VirtualMachineError)? I can't imagine there is much you can do after something that serious.
If you're writing a dispatcher queue, then by the time the exception comes back to you there's no point in doing anything with it other than logging it. The Swing event queue has basically that type of behavior.
Alternatively, you could provide a hook for an "uncaught exception handler," similar to ThreadGroup. Be aware that the handler could take a long time, and end up delaying your dispatcher.
As far as InterruptedException goes: the only thing that cares about that is your dispatch loop, which should be checking some external state to see if it should stop processing.
I have the following code in a Runnable that gets passed to a thread t:
public void run() {
logger.debug("Starting thread " + Thread.currentThread());
try {
doStuff();
} catch (Exception e) {
logger.debug("Exception in Thread " + Thread.currentThread());
}
logger.debug("End of thread " + Thread.currentThread());
}
I've hit a bug where I see deadlock with the following conditions
only the start of thread message has been printed by my logs
A thread dump shows that the thread t (supposed to be executing this) is no longer running
Is there some magical way this thread could have terminated early without either logging an end of thread message OR throwing an exception?
Are you sure that doStuff() did not throw an Error? Change catch (Exception e) to catch (Throwable t). It's possible to kill threads in Java with Thread.stop(), but that is highly unlikely.
Are you sure that where you start() the Thread, you also join() it afterwards?
Runnable myRunnable=new Runnable(){
#Override
public void run(){
// your original code goes here
}
};
Thread myThread=new Thread(myRunnable);
myThread.start();
myThread.join(); // magic happens here! it waits for the thread to finish ;)
By the way, join() may throw an InterruptedException,
so if something interrupts your thread while it's running,
join will inform you about this by throwing this exception.
Hope this helps.
When you catch Exception, you will catch any RunnableException and any declared thrown Exception, but you will not catch anything that extends Error. If you truly want to catch anything, then you need to catch Throwable.
If you want to do this for logging purposes only and you don't care why the Thread exits, you can do this:
public void run() {
logger.debug("Starting thread " + Thread.currentThread());
try {
// The work of your Thread
} finally {
logger.debug("End of thread " + Thread.currentThread());
}
}
and the finally statement is guaranteed to execute unless the Thread is stopped or deadlocks or in some other way stops executing without an Exception.
In most of my programs, I install an UncaughtExceptionHandler so that I'll know about every Thread that dies unexpectedly. It's been a tremendous help in tracking failures. This was added to the language as of Java 5.
Sure, the thread could get interrupted after the end of the try/catch block but before the last logger.debug statement. In that case it would throw an InterruptedException that, in principle, might not get recorded anywhere (if the default exception handler is set to ignore such things).
That seems like a rather unlikely scenario, though... it's kind of hard to tell what's going on without knowing more about the rest of your program, though.
When ever you trap a general exception I suggest you log it so you know what the exception was and it cause. Failing to do so will not help you at all.