I have following sample created to mimic the situation i am encountering related to ExecutionService shutdown process. It seems that it terminates only one thread out of 3 something... and i get error messages on tomcat server.
public class Test {
static final ExecutorService threadExecutor = Executors.newCachedThreadPool();
static Runnable getTask(final String name) {
return new Thread() {
#Override
public void run() {
this.setName("Thread-" + name);
while (true) {
try {
System.out.println(name + " running...[" + this.getName() + "]");
Thread.sleep(10000);
} catch (InterruptedException e) {
System.out.println("InterruptedException..." + this.getName());
throw new Exception(e);
}
}
}
};
}
public static void main(String... strings) {
threadExecutor.submit(getTask("Task-1"));
threadExecutor.submit(getTask("Task-2"));
threadExecutor.submit(getTask("Task-3"));
//--
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
ThreadPoolExecutor tpe = (ThreadPoolExecutor) threadExecutor;
System.out.println("Active Threads=====>" + tpe.getActiveCount());
tpe.shutdown();
try {
if (!threadExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
System.out.println("Executor did not terminate in the specified time.");
List<Runnable> droppedTasks = tpe.shutdownNow();
System.out.println("Shutdown thread pool forecibly. " + droppedTasks.size() + " tasks will not be executed.");
}
System.out.println("Active Threads=====>" + tpe.getActiveCount());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
shutdown() initiates the shutdown process within the thread pool but allows current running tasks to finish. In your example the task does not finish because of while(true).
shutdownNow() initiates the shutdown and also interrupts the currently running threads. But again your task is handling that interrupted exception and running the while(true) loop.
I think you can simply share a common boolean between your tasks and caller code from where you are calling the threadPoolExecuror.shutdown(). Use that boolean in task instead of while(true).
Related
I've got simple test code:
public static void main(String[] args) {
CompletionService<Integer> cs = new ExecutorCompletionService<>(Executors.newCachedThreadPool());
cs.submit(new Callable<Integer>() {
public Integer call(){
try{
Thread.sleep(3000); // Just sleep and print
System.out.println("Sleeping thread: " + Thread.currentThread().getId());
}catch(InterruptedException e){
e.printStackTrace();
}
return 10;
}
});
try{
Future<Integer> fi = cs.take();
System.out.println(fi.get());
}catch(Exception e){
e.printStackTrace();
}
}
I run it, sleep 3 seconds, and prints
Sleeping thread: 14
10
But then it hangs there, the program doesn't end.
What's happening, how to make it finish?
As mentioned in the comments by tgdavies, your program will exit after +/- 60 seconds, because that is the default timeout for a thread without tasks in an ExecutorService created by Executors.newCachedThreadPool().
If you don't want to wait for 60 seconds, you should shutdown the executor service after you're done submitting tasks.
For example:
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
try {
CompletionService<Integer> cs = new ExecutorCompletionService<>(executorService);
cs.submit(new Callable<Integer>() {
public Integer call() {
try {
Thread.sleep(3000); // Just sleep and print
System.out.println("Sleeping thread: " + Thread.currentThread().getId());
} catch (InterruptedException e) {
e.printStackTrace();
}
return 10;
}
});
try {
Future<Integer> fi = cs.take();
System.out.println(fi.get());
} catch (Exception e) {
e.printStackTrace();
}
} finally {
executorService.shutdown();
}
}
Alternatively, configure the executor service to create daemon threads using a custom ThreadFactory. Only do this if it is not a problem that an executor service that is doing actual work gets "killed" when there are no more normal (non-daemon) threads.
This question already has answers here:
ThreadPoolExecutor Block When its Queue Is Full?
(10 answers)
Closed 3 months ago.
We have a large text file in which each line requires intensive process. The design is to have a class that reads the file and delegates the processing of each line to a thread, via thread pool. The file reader class should be blocked from reading the next line once there is no free thread in the pool to do the processing. So i need a blocking thread pool
In the current implementation ThreadPoolExecutor.submit() and ThreadPoolExecutor.execute() methods throw RejectedExecutionException exception after the configured # of threads get busy as i showed in code snippet below.
public class BlockingTp {
public static void main(String[] args) {
BlockingQueue blockingQueue = new ArrayBlockingQueue(3);
ThreadPoolExecutor executorService=
new ThreadPoolExecutor(1, 3, 30, TimeUnit.SECONDS, blockingQueue);
int Jobs = 10;
System.out.println("Starting application with " + Jobs + " jobs");
for (int i = 1; i <= Jobs; i++)
try {
executorService.submit(new WorkerThread(i));
System.out.println("job added " + (i));
} catch (RejectedExecutionException e) {
System.err.println("RejectedExecutionException");
}
}
}
class WorkerThread implements Runnable {
int job;
public WorkerThread(int job) {
this.job = job;
}
public void run() {
try {
Thread.sleep(1000);
} catch (Exception excep) {
}
}
}
Output of above program is
Starting application to add 10 jobs
Added job #1
Added job #2
Added job #3
Added job #4
Added job #5
Added job #6
RejectedExecutionException
RejectedExecutionException
RejectedExecutionException
RejectedExecutionException
Can some one throw some light i.e how i can implement blocking thread pool.
Can some one throw some light i.e how i can implement blocking thread pool.
You need to set a rejection execution handler on your executor service. When the thread goes to put the job into the executor, it will block until there is space in the blocking queue.
BlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(3);
ThreadPoolExecutor executorService =
new ThreadPoolExecutor(1, 3, 30, TimeUnit.SECONDS, arrayBlockingQueue);
// when the blocking queue is full, this tries to put into the queue which blocks
executorService.setRejectedExecutionHandler(new RejectedExecutionHandler() {
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
// block until there's room
executor.getQueue().put(r);
// check afterwards and throw if pool shutdown
if (executor.isShutdown()) {
throw new RejectedExecutionException(
"Task " + r + " rejected from " + executor);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RejectedExecutionException("Producer interrupted", e);
}
}
});
So instead of the TRE throwing a RejectedExecutionException, it will call the rejection handler which will in turn try to put the job back on the queue. This blocks the caller.
Lets have a look at your code again:
for (int i = 1; i <= Jobs; i++)
try {
tpExe.submit(new WorkerThread(i));
System.out.println("job added " + (i));
} catch (RejectedExecutionException e) {
System.err.println("RejectedExecutionException");
}
So - when you try to submit, and the pool is busy, that exception is thrown. If you want to wrap around that, it could look like:
public void yourSubmit(Runnable whatever) {
boolean submitted = false;
while (! submitted ) {
try {
tpExe.submit(new WorkerThread(whatever));
submitted = true;
} catch (RejectedExecutionException re) {
// all threads busy ... so wait some time
Thread.sleep(1000);
}
In other words: use that exception as "marker" that submits are currently not possible.
You can use semaphore for to control the resource.Reader will read and create asynchronous task by acquiring semaphore.If every thread is busy the reader thread will wait till thread is available.
public class MyExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command)
throws InterruptedException, RejectedExecutionException {
semaphore.acquire();
try {
exec.execute(new Runnable() {
public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
throw e;
}
}
}
Here is a RejectedExecutionHandler that supports the desired behavior. Unlike other implementations, it does not interact with the queue directly so it should be compatible with all Executor implementations and will not deadlock.
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.BiFunction;
import static com.github.cowwoc.requirements.DefaultRequirements.assertThat;
import static com.github.cowwoc.requirements.DefaultRequirements.requireThat;
/**
* Applies a different rejection policy depending on the thread that requested execution.
*/
public final class ThreadDependantRejectionHandler implements RejectedExecutionHandler
{
private final ThreadLocal<Integer> numberOfRejections = ThreadLocal.withInitial(() -> 0);
private final BiFunction<Thread, Executor, Action> threadToAction;
/**
* #param threadToAction indicates what action a thread should take when execution is rejected
* #throws NullPointerException if {#code threadToAction} is null
*/
public ThreadDependantRejectionHandler(BiFunction<Thread, Executor, Action> threadToAction)
{
requireThat(threadToAction, "threadToAction").isNotNull();
this.threadToAction = threadToAction;
}
#SuppressWarnings("BusyWait")
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor)
{
if (executor.isShutdown())
return;
Thread currentThread = Thread.currentThread();
Action action = threadToAction.apply(currentThread, executor);
if (action == Action.RUN)
{
r.run();
return;
}
if (action == Action.REJECT)
{
throw new RejectedExecutionException("The thread pool queue is full and the current thread is not " +
"allowed to block or run the task");
}
assertThat(action, "action").isEqualTo(Action.BLOCK);
int numberOfRejections = this.numberOfRejections.get();
++numberOfRejections;
this.numberOfRejections.set(numberOfRejections);
if (numberOfRejections > 1)
return;
try
{
ThreadLocalRandom random = ThreadLocalRandom.current();
while (!executor.isShutdown())
{
try
{
Thread.sleep(random.nextInt(10, 1001));
}
catch (InterruptedException e)
{
throw new WrappingException(e);
}
executor.submit(r);
numberOfRejections = this.numberOfRejections.get();
if (numberOfRejections == 1)
{
// Task was accepted, or executor has shut down
return;
}
// Task was rejected, reset the counter and try again.
numberOfRejections = 1;
this.numberOfRejections.set(numberOfRejections);
}
throw new RejectedExecutionException("Task " + r + " rejected from " + executor + " because " +
"the executor has been shut down");
}
finally
{
this.numberOfRejections.set(0);
}
}
public enum Action
{
/**
* The thread should run the task directly instead of waiting for the executor.
*/
RUN,
/**
* The thread should block until the executor is ready to run the task.
*/
BLOCK,
/**
* The thread should reject execution of the task.
*/
REJECT
}
}
This works for me.
class handler implements RejectedExecutionHandler{
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I've done a simple test, and code as below :
public class InterruptTest
{
public static class MyTask implements Runnable {
#Override
public void run() {
System.out.println("before sleep " + Thread.currentThread().isInterrupted());
System.out.println(Thread.currentThread());
Thread.currentThread().interrupt();
System.out.println("after sleep " + Thread.currentThread().isInterrupted());
}
}
public static void main(String[] str)
{
ExecutorService service = Executors.newFixedThreadPool(1);
// MyTask task1 = new MyTask();
Future<?> future1 = service.submit(new InterruptTest.MyTask());
Future<?> future2 = service.submit(new InterruptTest.MyTask());
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
System.out.println("interrupted;");
}
}
}
And the output is :
before sleep false
Thread[pool-1-thread-1,5,main]
after sleep true
**before sleep false** // line 4
Thread[pool-1-thread-1,5,main]
after sleep true
why line 4 still output false ? not true ? Cause there is only one thread in current pool, and it should have been interrupted in the first task, why it's still available (not interrupted) when the second task runs ?
Thanks in advance!
Another question is I modify the run function as below :
public static class MyTask implements Runnable {
#Override
public void run() {
System.out.println("before sleep " + Thread.currentThread().isInterrupted());
System.out.println(Thread.currentThread());
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
System.out.println("interrupted;");
System.out.println("after sleep " + Thread.currentThread().isInterrupted());
System.out.println(Thread.currentThread());
}
}
}
And the output of one task is :
before sleep false
Thread[pool-1-thread-1,5,main]
interrupted;
after sleep false
The task should be waked up from sleep by thread.interrupt. But when I use Thread.currentThread().isInterrupted() to check it, it still return false.
Will sleep() eat the interrupt state ??
Looking at the source code of ThreadPoolExecutor, there is a private method called clearInterruptsForTaskRun documented as:
Ensures that unless the pool is stopping, the current thread does not have its interrupt set
What the right way to interrupt executor's thread?
I've got this:
Thread class with name Worker with method:
public void run() {
while(!(Thread.currentThread().isInterrupted()){
System.out.println("work " + Thread.currentThread().getName() + ":" + Thread.currentThread().isInterrupted());
}
}
And main class with:
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
Worker worker = new Worker();
executorService.execute(worker);
I try to call worker.interrupt(); or executorService.shutdownNow(); but my thread goes on and isInterrupted() is false.
Can you post all the relevant code? Based on the information you have given, I can't reproduce the behaviour you describe. See below a SSCCE that works as expected - output:
work pool-1-thread-1:false
work pool-1-thread-1:false
work pool-1-thread-1:false
....
Thread has been interrupted
Code:
public class Test {
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(1);
Worker worker = new Worker();
executorService.execute(worker);
executorService.shutdownNow();
}
public static class Worker extends Thread {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("work " + Thread.currentThread().getName() + ":" + Thread.currentThread().isInterrupted());
}
System.out.println("Thread has been interrupted");
}
}
}
Sorry if the question is quite simple. I am a beginner.
I have to create thread that calulates something, while the first thread works the other one have to measure if the first thread calculate the function in specified time. If not, it has to throw exception. Else it returns the answer.
I'd take the java.util.concurrent components - simple example
public void myMethod() {
// select some executor strategy
ExecutorService executor = Executors.newFixedThreadPool(1);
Future f = executor.submit(new Runnable() {
#Override
public void run() {
heresTheMethodToBeExecuted();
}
});
try {
f.get(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// do something clever
} catch (ExecutionException e) {
// do something clever
} catch (TimeoutException e) {
// do something clever
}
}
Have your thread notify a synchronization object when it is done and have your other thread wait x number of milliseconds for it to finish.
public class Main {
private static final Object mThreadLock = new Object();
static class DoTaskThread extends Thread {
public void run() {
try {
int wait = new Random().nextInt(10000);
System.out.println("Waiting " + wait + " ms");
Thread.sleep(wait);
} catch (InterruptedException ex) {
}
synchronized (mThreadLock) {
mThreadLock.notifyAll();
}
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
synchronized (mThreadLock) {
DoTaskThread thread = new DoTaskThread();
thread.start();
try {
// Only wait 2 seconds for the thread to finish
mThreadLock.wait(2000);
} catch (InterruptedException ex) {
}
if (thread.isAlive()) {
throw new RuntimeException("thread took too long");
} else {
System.out.println("Thread finished in time");
}
}
}
}
join is a lot simpler than using a lock.
join (millis)
Waits at most millis milliseconds
for this thread to die. A timeout of 0
means to wait forever.
Example code:
Thread calcThread = new Thread(new Runnable(){
#Override
public void run() {
//some calculation
}
});
calcThread.start();
//wait at most 2secs for the calcThread to finish.
calcThread.join(2000);
//throw an exception if the calcThread hasn't completed.
if(calcThread.isAlive()){
throw new SomeException("calcThread is still running!");
}
Have a look at http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination(long,%20java.util.concurrent.TimeUnit) which allows you to handle this without dealing with thread synchronization yourself.