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);
Related
I'm pretty new to Java multi threading, I've found a few responses for what I'm trying to do. However being new to java threading I'm still having a hard time following the responses.
Basically this is what I've got:
private final ExecutorService mFixedThreadPool;
public ThreadPool(int threadCount) {
mFixedThreadPool = Executors.newFixedThreadPool(threadCount);
}
public interface Task {
void phase1();
void phase2();
void phase3();
}
public void executeBatch(List<Runnable> tasks) {
tasks.forEach(task -> mFixedThreadPool.execute(task::phase1));
tasks.forEach(task -> mFixedThreadPool.execute(task::phase2));
tasks.forEach(task -> mFixedThreadPool.execute(task::phase3));
//only return on the main thread once all the tasks are complete.
//(Dont destroy threadpool as the "executeBatch" method will be called in a loop)
}
I want to pause or stop or wait on the thread that calls "executeBatch" until the batch of work is complete. I know it's possible to do this using mFixedThreadPool.shutdown() then waiting till its shutdown successfully, however I would like to reuse the threads many times very often so shutting down each time is inefficient.
If what you want is a thread pool that doesn't start the next thread until the previous one has finished you can simply create a FixedThreadPool with one thread:
ExecutorService threadPool = Executors.newFixedThreadPool(1);
If what you want is sleep your current thread until the pool has finished using shutdown. shutdown() is meant precisely for this kind of task, but after shutdown you will need to create a new ExecutorService:
threadPool.shutdown();
try {
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
...
}
You could encapsulate your ExecutorService in an ExecutorCompletionService. This will notify you when it finishes without shutting down the Executor, like you want. See some info here.
One last option is using Future. The get() method blocks until that thread has finished so you could:
ExecutorService threadPool = Executors.newFixedThreadPool(4);
List<Callable<String>> tasks = new ArrayList<>();
List<Future<String>> futures = new ArrayList<>();
List<String> result = new ArrayList<>();
tasks.stream().forEachOrdered(task -> futures.add(threadPool.submit(task)));
for (Future<String> future :futures) {
try {
result.add(future.get());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I think fork/join framework can give you what you want.
You can control the execution and if needed unfork tasks and compute it in main thread.
I have a Java 8 application where I run a task on a thread:
Thread t = new Thread(() -> { runTask();
finalizeTask(); });
t.start()
saveThread(t);
At some point, from a different thread, this task may be interrupted:
Thread t = getThread(); // Obtains thread t
t.interrupt();
With this, I want the runTask(); line to be interrupted, but I'd still like the finalizeTask(); to run.
How can I catch the thread interruption and deal with it?
You can use try catch finally for this.
try {
runTask();
}
catch (InterruptedException e) {
// Log etc.
}
finally {
finalizeTask();
}
This will ensure that that finalizeTask always executes.
I have the following code in a class which contains my main method
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable formatConcentration = new formatConcentration(87);
executor.execute(formatConcentration);
System.out.println("Called an instance of formatConcentration");
while (!executor.isTerminated())
{
//stay Alive
Thread.sleep(1000);
System.out.println("Still alive");
}
System.out.println("Program successfully finished");
return;
This creates an instance of formatConcentration class. The code for which is the following (I've taken all of my functionality out for the sake of the example).
public class formatConcentration extends Thread{
private int numberOfNewRows;
formatConcentration(int rows)
{
this.numberOfNewRows = rows;
}
public void run() {
System.out.println("Running the Formatting Script");
final int numberOfNewRegistered = this.numberOfNewRows;
try
{
System.out.println("Finished formatting");
}//end of try
catch (Exception e1)
{
log.log(e1.toString());
log.closeLog() ;
System.exit(1) ;
}
System.out.println("Still Finished formatting");
return;
}
}
My problem is that once return is invoked it does not terminate the thread.
I have done quite a lot of looking around and as far as I can tell this should be fine but I would imagine that I'm overlooking something small and would appreciate fresh eyes on the problem.
Or if someone has a suggestion of how to kill the thread from inside the run(){} method I would greatly appreciate it (preferably not by setting a variable that I'll check in the main class but if that's how I have to do it so be it) as I know that once it reaches the return statement it's finished and no longer need any reference to variables created in run().
The output generated to the console is as follows:
Called an instance of formatConcentration
Running the Formatting Script
Finished formatting
Still Finished formatting
Still alive
Still alive
Still alive
Still alive
Still alive
etc.
You never shutdown the executor. From the Javadocs for isTerminated:
Returns true if all tasks have completed following shut down. Note that isTerminated is never true unless either shutdown or shutdownNow was called first.
As long as you don't shutdown the executor, you can submit new tasks to it for execution. isTerminated does not check the state of the submitted tasks, it checks the state of the ExecutorService itself.
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable formatConcentration = new formatConcentration(87);
executor.execute(formatConcentration);
System.out.println("Called an instance of formatConcentration");
executor.shutdown();
while (!executor.isTerminated())
{
//stay Alive
Thread.sleep(1000);
System.out.println("Still alive");
}
System.out.println("Program successfully finished");
return;
Another simpler way to do it would be :
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable formatConcentration = new formatConcentration(87);
executor.execute(formatConcentration);
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Executor awaitTermination method substitutes your loop.
ExecutorService is mainly used to delegate your jobs to separte workers.
Using this only most of the Connection pooling libs have been created.
So this service will be initiated whenever your application is started and will be closed (manually) by your application's closing method.
In your program you should write a code to check the executor service's status,
Is any workers are currently working...
If no workers are in busy mode then just stop accepting any further tasks.
From javadocs see the sample shutdown code,
The following method shuts down an ExecutorService in two phases, first by calling shutdown to reject incoming tasks, and then calling shutdownNow, if necessary, to cancel any lingering tasks:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
Hope it will give some information to you.
I have an Executor that needs to terminate before I can shut down another Executor, I was thinking about trying to implement a wait-notify tactic, but the notification will have to come from executor.isTerminated(), so unless I subclass it, I can't notify the shutdown thread. Is there an alternative to sub-classing it, or spin waiting?
I think maybe you want a synchronous termination of the executor. Always we can use a workaround to do this:
//THE LOGIC BEFORE YOU WANT TO WAIT THE EXECUTOR
...
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
//THE LOGIC AFTER THE EXECUTOR TERMINATION
...
Using the awaitTermination method with a MAX_VALUE time.
Executor executor = Executors.newFixedThreadPool(YOUR_THREAD_COUNT);
exector.shutDown();
boolean shutdown = false;
try {
shutdown = executor.awaitTermination(YOUR_TIME_OUT, TimeUnit.MILLISECOND);
} catch (InterruptedException e) {
// handle the exception your way
}
if (!shutdown) {
LOG.error("Executor not shut down before time out.");
}
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.