I'm currently attempting to write a Logger style thread. I'm not using the existing API because this is partially an exercise to improve my threading.
When the thread is interrupted, I need it to shutdown gracefully, flushing the last of it's queued messages and closing the file streams.
Currently, it shuts down but messages are often still in queue, and I'm concerned that the file streams aren't being closed gracefully.
This is my run()
while(!shutdown){
writeMessages();
try{
Thread.sleep(5000);
}
catch (InterruptedException e) {
}
}try {
writeMessages();
} catch (CustomException e1) {
e1.printStackTrace();
}
try {
logFile.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
errFile.close();
} catch (IOException e) {
e.printStackTrace();
}
Java has very neat way to shutdown threads. It's called interruption flag. When you want to interrupt thread you simply write following code:
thread.interrupt();
thread.join();
And in the Runnable of background thread you should check interruption flag and behave accordingly. If you want thread to survive until messages are left you can do it in a following manner (I assume you have some way of checking is there any messages left. In my case it's a BlockingQueue):
Thread self = Thread.currentThread();
BlockingQueue<String> messages = ...;
while (!self.isInterrupted() || !messages.isEmpty()) {
try {
String message = messages.take();
writeMessage(message);
} catch (InterruptedException) {
self.interrupt();
}
}
One more thing. You should ensure that messages are not added to the queue after thread shutdown is requested or shutdown all threads generating messages before writing thread. This also could be done checking thread interruption flag (you need to know reference to a writer thread):
public void addMessage(String message) {
if (thread.isInterrupted() || !thread.isAlive()) {
throw new IllegalStateException();
}
messages.add(message);
}
Also I recommends you to see at java.util.concurrent package. It have a lot of useful tools for multithreaded applications.
Use the finally block to add your flushing instructions.
All other comments are good, I just want to add - make sure that you called flush() on your output streams before closing them.
Related
Problem
I am using a completion service and spawning child threads to perform some ETL.
As I debug in my IDE and then stop all processes, I notice I still have a bunch of zombie threads killing my CPU. This is due to the fact that I'm not terminating the child threads properly.
Minimum Example
Future<Boolean> future = completionService.submit(conversionProcessor);
boolean isCompleted = false;
while (!isCompleted && !closed.get()) {
try {
isCompleted = future.get(CONSUMER_HEARTBEAT_INTERVAL,
TimeUnit.SECONDS); // Wait until heartbeat interval exceeds
if (isCompleted) {
// do some things here
future.cancel(true);
break;
}
} catch (TimeoutException e) {
// Used to keep consumer alive in the cluster
consumer.poll(Duration.ofSeconds(CONSUMER_HEARTBEAT_INTERVAL)); // does heart-beat
} catch (CancellationException e) {
future.cancel(true);
break;
} catch (InterruptedException e) {
future.cancel(true);
break;
} catch (WakeupException we) {
future.cancel(true);
break;
} catch (Exception e) {
future.cancel(true);
break;
}
Thoughts
Essentially, I submit my Callable<Boolean> to my completion service.
ExecutorCompletionService<Boolean> completionService = new ExecutorCompletionService<>(
Executors.newSingleThreadExecutor());
If I stop the debugger, this thread is presumably still running. I just added this future.cancel(true) piece, which seems to have stopped continuously uploaded files from my child thread, but I still see these java processes running on my activity monitor.
I'm wondering how I should be thinking about this? I want the callable as it tells me when the underlying ETL has completed or not (true/false)
edit:
future.cancel actually seems to be helping quite a bit.. Is this what I want to be using?
Once you are done with your CompletionService you need to shutdown underlying executor so you need to do the following
ExecutorService es = Executors.newSingleThreadExecutor();
ExecutorCompletionService<Boolean> completionService = new ExecutorCompletionService<>(es);
And a the end call
es.shutdown();
es.awaitTermination(1, TimeUnit.SECONDS);
While solving the task, I've noticed a behavior I can not explain.
My task was to read from InputStream and interrupt that reading after a timeout. Even though lots of people say blocking read can not be interrupted, I've achieved that goal using CompletableFuture
public void startReader() {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> doRead(System.in));
future.get(5, TimeUnit.SECONDS);
}
private void doRead(InputStream in) {
try {
new BufferedReader(new InputStreamReader(in)).readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
But when I implement the same using Future, I can see TimeoutException been thrown into JVM, but I still can see that reading thread was not terminated and still running.
public void startReader() throws ExecutionException, InterruptedException, TimeoutException {
Future<?> future = Executors.newSingleThreadExecutor().submit(() -> doRead(System.in));
future.get(5, TimeUnit.SECONDS);
}
private void doRead(InputStream in) {
try {
new BufferedReader(new InputStreamReader(in)).readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
Why there is such a difference? I believe CompletableFuture does not make any magic
Neither of your code snippets will stop the "reading" thread when you reached the future.get(5, TimeUnit.SECONDS);. They will continue waiting for your input from System.in. If you want to stop it you should send an interrupt to that thread and hope the thread react on it. Or you can force kill the thread, obviously.
However, the CompletableFuture.runAsync() and Executors.newSingleThreadExecutor() calls use different threads, specially using different daemon flags (see What is a daemon thread in Java?). When you place a System.out.println(Thread.currentThread().isDaemon()); inside your doRead() method you will see that CompletableFuture.runAsync uses a daemon thread (so it doesn't block the JVM from terminating) where Executors.newSingleThreadExecutor() does not (and keeps the JVM alive).
I'm using Jetty 9.3 with WebSockets API (not jsr 356).
Different threads can send different text messages to the same session/endpoint and I'm trying to synchronize this so only one message is sent to the same session at the time.
Here is the code I'm using:
private final ReentrantLock lock = new ReentrantLock();
public void sendTextMessage(String s){
try {
boolean isLock=this.lock.tryLock(5, TimeUnit.SECONDS);
if(isLock){
this.session.getRemote().sendString(s);
}else{
System.out.println("message not send :"+ip);
}
} catch (IOException e) {
} catch (InterruptedException e) {
}
finally{
if(this.lock.isHeldByCurrentThread())
this.lock.unlock();
}
}
After a certain amount of time some threads remain blocked. This is not very common. To give you some stats: 17554165 messages sent -> 3 threads blocked.
Am I doing something wrong? Is there a better way to implement this?
Is it possible that this.session.getRemote().sendString(s); is not terminated and is keeping the thread locked?
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Does a finally block always run?
I learned that the finally clause of a try catch statement, executes always. But some guy said to me that it is possible to avoid executing it(removing it is not an option).
-Does someone how is that possible?
-Also i am curious in knowing why would someone want to avoid to execute it?
Kill it with an uncaught exception within the finally block, or kill the overall JVM (which kills the thread, among other things).
There is no good reason to stop the execution of a finally block except poor design. If it's not supposed to run every time, then don't put it in a finally block.
Using the below test code, I run two different scenarios to see what happens when killing the Thread:
Start the Thread and sleep the main thread for 2 seconds. Within the Thread, pretty much immediately enter the finally block and then sleep for 5 seconds. Once the main thread is finished waiting, kill the Thread using stop.
Start the Thread and sleep 2 seconds. Within the Thread, sleep 5 seconds before entering the finally block and then sleep some more within the finally to give it a chance to be killed.
In the first case, the result is that the finally block stops executing.
In the second case, the result is that the finally block executes completely, and on the Thread that was stopped no less.
Output (note the name of the current thread added for all output):
thread-starting [main]
trying [Thread-0]
catching [Thread-0]
finally-sleeping [Thread-0]
thread-stopped [main]
[main]
thread-starting [main]
trying-sleeping [Thread-1]
thread-stopped [main]
finally-sleeping [Thread-1]
finally-done [Thread-1]
Code:
public class Main
{
public static void main(String[] args)
{
testThread(new TestRunnable());
println("");
testThread(new TestRunnable2());
}
private static void testThread(Runnable runnable)
{
Thread testFinally = new Thread(runnable);
println("thread-starting");
testFinally.start();
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
println("main-interrupted...");
}
testFinally.stop();
println("thread-stopped");
}
private static class TestRunnable implements Runnable
{
#Override
public void run()
{
try
{
println("trying");
throw new IllegalStateException("catching");
}
catch (RuntimeException e)
{
println(e.getMessage());
}
finally
{
println("finally-sleeping");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
println("finally-interrupted");
}
println("finally-done");
}
}
}
private static class TestRunnable2 implements Runnable
{
#Override
public void run()
{
try
{
println("trying-sleeping");
Thread.sleep(5000);
}
catch (InterruptedException e)
{
println("trying-interrupted");
}
finally
{
println("finally-sleeping");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
println("finally-interrupted");
}
println("finally-done");
}
}
}
private static void println(String line)
{
System.out.printf("%s [%s]%n", line, Thread.currentThread().getName());
System.out.flush();
}
}
-Does someone how is that possible?
System.exit(0);
-Also i am curious in knowing why would someone want to avoid to execute it?
To answer questions like these and appear smart. ;)
BTW, Thread.stop() doesn't prevent finally being called.
Thread t = new Thread() {
#Override
public void run() {
try {
System.out.println("Thread start");
Thread.sleep(1000);
System.out.println("Thread end");
} catch (InterruptedException ie) {
System.out.println("Thread Interrupted");
} catch (Error e) {
System.out.println("Thread threw an error " + e);
throw e;
} finally {
System.out.println("Thread finally");
}
}
};
t.start();
t.join(100);
t.stop();
prints
Thread start
Thread threw an error java.lang.ThreadDeath
Thread finally
There's no way of avoiding it, unless something external happens such as the Java Virtual Machine shutting down.
As a general rule you should always assume that a finally block will run. The whole point of it is to ensure that it runs regardless of what happens in the try block - there should be no reason to avoid it!
To your first question i think the only way that comes to my mind is by creating an infinite loop or something.(But it makes no sense at all)
try{
while(true);
}
catch(Exception e) {
}
finally {
//..
}
To your second question, i don't really know why would someone want to do something like that
See this link: https://stackoverflow.com/posts/6228601/edit
I can't think of a good reason that you would want to avoid a finally block. If you really don't want to use this feature, then just don't implement a finally block (at your own risk however).
Killing the JVM would do it, but that's not really an acceptible solution for any production code.
Why is removing a finally block not an option?
Can anyone provide examples in Java, or advise about implementing a class which asynchronously reads lines from a socket and puts each line into a BlockingQueue. Assume the socket is connected, and the BlockingQueue and consumer already exists.
Edit: One more thing, it needs to have the ability to timeout after a period of inactivity, and stop immediately on command.
It's not homework, I simply have not been able to find complete examples for how to do this well, and reliably.
Thank you very much.
You sound like you've already done the work, to be honest. All you need to do is create a BlockingQueue and have a thread to process it which is your consumer I guess. Assuming you have a DataInputStream 'in'...
Something like this:
BlockingQueue<String> receivedQueue = new LinkedBlockingQueue<String>();
public void run()
{
while (true)
{
try
{
receivedQueue.put(in.readUTF());
} catch (EOFException e)
{
ch.getClient().disconnect();
break;
} catch (IOException e)
{
break;
} catch (InterruptedException e)
{
break;
}
}
theQueueProcessor.interrupt();
}