In Java library thread pool implementations, usually shutting down a pool means:
-stop accepting new tasks
-previously submitted tasks are executed
-all pool threads are terminated
Regarding the last point, how would you stop a pool thread that could potentially try to take a new task, after it has been stopped?
My threads do something like this (in java pseudo code):
public void run() {
while(!isStopped) {
Task task = taskQueue.take(); //line1
task.run(); //line2
}
}
and have a method stop:
public synchronized void stop(){
isStopped = true;
this.interrupt();
}
In my thread pool class, I have a method stop:
public synchronized void shutdown(){
this.isShutdown = true; //to stop the whole pool
for(PoolThread thread : threads)
thread.stop();
}
The point is, if a thread reaches line 1, isStopped was false, but at that same moment it could be set to true by the pool class. How do I remember that I should stop the thread again? Does calling interrupt suffice?
Send the shutdown messages through the task queue:
static Task stop = // some special value
public void run() {
while (true) {
Task task = taskQueue.take();
if (task == stop) {
break;
}
task.run();
}
}
and in shutDown:
public synchronized void shutdown(){
if (isShutdown) {
return;
}
this.isShutdown = true;
for(PoolThread thread : threads) {
taskQueue.put(PoolThread.stop);
}
}
With a number of shutdown messages in the queue equal to the number of threads, once all work is completed, the threads will each take a shutdown message and shut down. (Note that we don't need to care about which thread gets which shutdown message.)
Related
I am reading Java Concurrency in Practice and encounter the following code snippet.
public class TrackingExecutor extends AbstractExecutorService {
private final ExecutorService exec;
private final Set<Runnable> tasksCancelledAtShutdown =
Collections.synchronizedSet(new HashSet<Runnable>());
...
public List<Runnable> getCancelledTasks() {
if (!exec.isTerminated())
throw new IllegalStateException(...);
return new ArrayList<Runnable>(tasksCancelledAtShutdown);
}
public void execute(final Runnable runnable) {
exec.execute(new Runnable() {
public void run() {
try {
runnable.run();
} finally {
if (isShutdown()
&& Thread.currentThread().isInterrupted())
tasksCancelledAtShutdown.add(runnable);
}
}
});
}
// delegate other ExecutorService methods to exec
}
The book says:
TrackingExecutor has an unavoidable race condition that could make it yield false positives: tasks that are identified as cancelled but actually completed. This arises because the thread pool could be shut down between when the last instruction of the task executes and when the pool records the task as complete.
Does it mean the below situation?
one worker thread has finished runnable.run(), but stop at finally block.
exec is shut down.
the worker thread executes finally block and add runnable into tasksCancelledAtShutdown. (runnable.run() has been finished, it should be recognized as finished, not cancelledAtShutdown.)
Do I get it right? If not, where is the race condition? What does "the thread pool could be shut down between when the last instruction of the task executes and when the pool records the task as complete" really mean?
Sample executor service
static class MyRunnable implements Runnable {
private String serverName;
public MyRunnable(String serverName) {
super();
this.serverName = serverName;
}
#Override
public void run() {
...
conn = new ch.ethz.ssh2.Connection(serverName);
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(user, pass);
logger.info("Connecting to " + server);
if (isAuthenticated == false) {
logger.info(server + " Please check credentials");
}
sess = conn.openSession();
...
}
}
public static void main(String[] args) {
List<String> serverList = ...;
ExecutorService executor = Executors.newFixedThreadPool(20);
for (String serverName : serverList) {
MyRunnable r = new MyRunnable(serverName);
executor.execute(r);
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
}
Right here is a sample code of my executor service. But with this logic when I meet a server that fails to connect or takes too long to connect it creates a a hang time within my application. I want to end/kill the thread if it takes longer than x amount of time to connect. How can I terminate the thread task if it does not connect to server within 2 seconds.
Attempt
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, 25, 500, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1));
I added the following code but apparently it does not end the thread if it takes longer than 2000 milliseconds.
Attempt 2
Future<?> future = executor.submit( new task));
try {
future.get(2000, TimeUnit.MILLISECONDS); // This waits timeout seconds; returns null
}
catch(TimeoutException e) {
future.cancel(true);
// System.out.println(server + "name");
}
How can I terminate the thread task if it does not connect to server within 2 seconds.
This is difficult thing to do typically because even if you interrupt the thread (like the other answers mention) there's no guarantee that the thread will stop. Interrupt just sets a flag on the thread and it's up to the code to detect the status and stop. This means that a ton of threads may be in the background waiting for the connects.
In your case however you are using the ch.ethz.ssh2.Connection.connect() method. Turns out there is a connect method that takes a timeout. I think you want the following:
// try to connect for 2 seconds
conn.connect(null, 2000, 0);
To quote from the connect method javadocs:
In case of a timeout (either connectTimeout or kexTimeout) a SocketTimeoutException is thrown.
You have to do awaitTermination() first, then check the return value, and then do shutdownNow(). shutdown() does not guarantee instant stoppage of the service, it just stops taking new jobs, and waits for all jobs to complete in order. shutdownNow() on the other hand, stops taking new jobs, actively attempts to stop all running tasks, and does not start any new one, returning a list of all waiting-to-execute jobs.
From JavaDocs :
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();
}
}
You can always call future.get(timeout...)
It will return timeout exception if it did not finish yet... then you can call future.cancel().
As long as you deal with threads in Java the only safe way to stop the thread is to interrupt it. You can call shutdown() first and then wait. This method doesn't interrupt threads.
If it doesn't help then you call shutdownNow() which tries to cancel tasks by setting interrupted flag of each thread to true. In that case if threads are blocked/waiting then InterruptedException will be thrown. If you check interrupted flag somewhere inside your tasks then you are good too.
But if you have no other choice but to stop threads you still can do it. One possible solution of getting access to workers is to trace all created threads inside ThreadPoolExecutor with help of custom thread factory.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class TestThreadPoolEx {
static class CustomThreadFactory implements ThreadFactory {
private List<Thread> threads = new ArrayList<>();
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
threads.add(t);
return t;
}
public List<Thread> getThreads() {
return threads;
}
public void stopThreads() {
for(Thread t : threads) {
if(t.isAlive()) {
try {
t.stop();
} catch (Exception e) {
//NOP
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
CustomThreadFactory factory = new CustomThreadFactory();
ExecutorService ex = Executors.newFixedThreadPool(1, factory);
ex.submit(() -> {
while(true);
});
ex.shutdown();
ex.awaitTermination(5, TimeUnit.SECONDS);
ex.shutdownNow();
ex.awaitTermination(5, TimeUnit.SECONDS);
factory.stopThreads();
}
}
This is sure unsafe but should fit your requirements. In this case it's able to stop while(true) loop. Cancelling tasks won't be able to do that.
I have the following code:
public class Driver {
private ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) {
Driver d = new Driver();
d.run();
}
private void run() {
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
#Override
public void run() {
System.out.println("Task is running!");
}
};
Runnable worker = new Runnable() {
#Override
public void run() {
timer.scheduleAtFixedRate(task, new Date(), 5 * 1000);
}
};
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Shutdown hook is being invoked!");
try {
if(executor.awaitTermination(20, TimeUnit.SECONDS))
System.out.println("All workers shutdown properly.");
else {
System.out.println(String.format("Maximum time limit of %s reached " +
"when trying to shut down workers. Forcing shutdown.", 20));
executor.shutdownNow();
}
} catch (InterruptedException interrupt) {
System.out.println("Shutdown hook interrupted by exception: " +
interrupt.getMessage());
}
System.out.println("Shutdown hook is finished!");
}
});
executor.submit(worker);
System.out.println("Initializing shutdown...");
}
}
When this runs I get the following console output:
Initializing shutdown...
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
... (this keeps going non-stop)
When I run this, the application never terminates. Instead, every 5 seconds, I see a new println of "Task is running!". I would have expected the main thread to reach the end of the main method, print "Initializing shutdown...", invoked the added shutdown hook, killed the executor, and finally print out "Shutdown hook is finished!".
Instead, "Task is running" just keeps getting printed and the program never terminates. What's going on here?
I am no expert but AFAIK you must have all non-Daemon threads terminated in order for the shutdown hook to “kick in”.
In the original example you have 3 non-Daemon:
The thread of “Main” – this is the only non-Daemon you want here..
The thread that runs the “TimerTask” – it is created by the “Timer” and you covered it by fixing to Timer(true)
The thread that runs the “worker” – it is created by the “executor” and in order for the “executor” to create Daemon threads you should create a ThreadFactory. (at least this is the way I know; there might be other ways...)
So I think what you should do is to create a ThreadFactory and use it when initializing the “executor”.
Create a class that will be the ThreadFactory:
private class WorkerThreadFactory implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "Worker");
t.setDaemon(true);
return t;
}
}
-- the important line is the setDaemon of course :)
Pass an instance of it as a parameter to the newCachedThreadPool method:
private ExecutorService executor = Executors.newCachedThreadPool(new WorkerThreadFactory());
Applying these 2 changes did the trick for me and I got to:
Maximum time limit of 20 reached when trying to shut down workers. Forcing shutdown.
Shutdown hook is finished!
Hope it helps,
Izik
golan2#hotmail.com
It is not shutting down because Timer() creates and starts a non-daemon thread ... which is then never stopped.
There are two things that can cause the JVM to shutdown of its own accord:
A call to System.exit() (or Runtime.halt())
The termination of the last remaining non-daemon thread.
Since you have created a second non-daemon thread (in addition to the thread that is running main()) the second condition won't be met.
Thread Pool like any ExecutorServices, we defined a newFixedPool of size 3. Now I have a queue of around 10000 runnable tasks.
For executing the above process I have these doubts -
To execute the above process , is the executor will let only 3 threads from the queus of tasks to run in one shot?
The Pool will be carrying 3 Threads , and those 3 threads will only be responsible for executing all the 10000 tasks. If it is correct , how a single thread is running different runnable tasks as finally those tasks are as well threads itself , and in the mid of the running of any of the job/tasks , you can assign new responsibility to the Pool Thread.
Yes, at most only 3 threads will be in the pool at once if in fact you are using Executors.newFixedThreadPool(3)
The 10,000 tasks are not Threads they are simply Runnables. A Thread has to be started via Thread#start to actually create a system thread. Tasks (instances of Runnable) are placed in a BlockingQueue. Threads from the thread pool will poll the BlockingQueue for a task to run. When they complete the task, they return to the queue to get another. If more tasks are added, then they are inserted into the BlockingQueue according to the rules of the implementation of that queue. For most queues this is First-In-First-Out, but a PriorityQueue actually uses a Comparator or natural ordering to sort tasks as they are inserted.
Below is customThreadPool in java which accept noofThreads and MaxConcurrentTask.
Also it has stop() to stop complete ThreadPool
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
#SuppressWarnings("all")
public class ThreadPool {
private BlockingQueue taskQueue = null;
private List<PoolThread> threads = new ArrayList<PoolThread>();
private boolean isStopped = false;
public ThreadPool(int noOfThreads, int maxNoOfTasks) {
taskQueue = new LinkedBlockingQueue(maxNoOfTasks);
for(int i=0; i<noOfThreads; i++) {
threads.add(new PoolThread(taskQueue));
}
for(PoolThread thread : threads) {
thread.start();
}
}
public synchronized void execute(Runnable task) {
if(this.isStopped)
throw new IllegalStateException("ThreadPool is stopped");
this.taskQueue.offer(task);
}
public synchronized void stop() {
this.isStopped = true;
for(PoolThread thread : threads) {
thread.stopMe();
}
}
}
#SuppressWarnings("all")
class PoolThread extends Thread {
private BlockingQueue taskQueue = null;
private boolean isStopped = false;
public PoolThread(BlockingQueue queue) {
taskQueue = queue;
}
public void run() {
while(!isStopped()) {
try {
Runnable runnable = (Runnable) taskQueue.poll();
runnable.run();
} catch(Exception e) {
//log or otherwise report exception, //but keep pool thread alive.
}
}
}
public synchronized void stopMe() {
isStopped = true;
this.interrupt();
//break pool thread out of dequeue() call.
}
public synchronized boolean isStopped() {
return isStopped;
}
}
When my application is ready to exit, either by closing a window or invoking the System.exit() method. Do I have to manually stop the threads I may have created or will Java take care of that for me?
In cases you use System.exit(). All the threads will stop whether or not they are daemon.
Otherwise, the JVM will automatically stop all threads that are daemon threads set by Thread.setDaemon(true). In other words, the jvm will only exit when only threads remaining are all daemon threads or no threads at all.
Consider the example below, it will continue to run even after the main method returns.
but if you set it to daemon, it will terminate when the main method (the main thread) terminates.
public class Test {
public static void main(String[] arg) throws Throwable {
Thread t = new Thread() {
public void run() {
while(true) {
try {
Thread.sleep(300);
System.out.println("Woken up after 300ms");
}catch(Exception e) {}
}
}
};
// t.setDaemon(true); // will make this thread daemon
t.start();
System.exit(0); // this will stop all threads whether are not they are daemon
System.out.println("main method returning...");
}
}
If you want stop threads before exit gracefully, Shutdown Hooks may be a choice.
looks like:
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
//Stop threads }
});
See: hook-design