I have a requirement for a task to be executed asynchronously while discarding any further requests until the task is finished.
Synchronizing the method just queues up the tasks and doesn't skip. I initially thought to use a SingleThreadExecutor but that queues up tasks as well. I then looked at the ThreadPoolExecutor but it reads the queue to get the task to be executed and therefore will have one task executing and a minimum of one task queued (the others can be discarded using ThreadPoolExecutor.DiscardPolicy).
The only thing I can think off is to use a Semaphore to block the queue. I've come with the following example to show what I'm trying to achieve. Is there a simpler way? Have I missed something obvious?
import java.util.concurrent.*;
public class ThreadPoolTester {
private static ExecutorService executor = Executors.newSingleThreadExecutor();
private static Semaphore processEntry = new Semaphore(1);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 20; i++) {
kickOffEntry(i);
Thread.sleep(200);
}
executor.shutdown();
}
private static void kickOffEntry(final int index) {
if (!processEntry.tryAcquire()) return;
executor.
submit(
new Callable<Void>() {
public Void call() throws InterruptedException {
try {
System.out.println("start " + index);
Thread.sleep(1000); // pretend to do work
System.out.println("stop " + index);
return null;
} finally {
processEntry.release();
}
}
}
);
}
}
Sample output
start 0
stop 0
start 5
stop 5
start 10
stop 10
start 15
stop 15
Taking axtavt's answer and transforming the above example gives the following simpler solution.
import java.util.concurrent.*;
public class SyncQueueTester {
private static ExecutorService executor = new ThreadPoolExecutor(1, 1,
1000, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
new ThreadPoolExecutor.DiscardPolicy());
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 20; i++) {
kickOffEntry(i);
Thread.sleep(200);
}
executor.shutdown();
}
private static void kickOffEntry(final int index) {
executor.
submit(
new Callable<Void>() {
public Void call() throws InterruptedException {
System.out.println("start " + index);
Thread.sleep(1000); // pretend to do work
System.out.println("stop " + index);
return null;
}
}
);
}
}
It looks like executor backed by SynchronousQueue with desired policy does what you want:
executor = new ThreadPoolExecutor(
1, 1,
1000, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
new ThreadPoolExecutor.DiscardPolicy());
if there is no queue, there is no need for an executor i'd say. using a semaphore alone seems enough. i'm using the code below to avoid running the same code when it is already running. just make sure the semaphore is static volatile, which makes the semaphore the only semaphore for the class and propagates the semaphore reference to other threads' heap as soon as it is changed
if (this.getSemaphore().tryAcquire()) {
try {
process();
} catch (Exception e) {
} finally {
this.getSemaphore().release();
}
}
else {
logger.info(">>>>> Job already running, skipping go");
}
Related
How to wait for all tasks to be completed when they are submitted using
ExecutorService.execute() . There is a function called awaitTermination
But a timeout has to be provided in it. Which is not a guarantee that when this
returns all the tasks would have been finished. Is there a way to achieve this ?
If you read the javadoc of the ExecutorService.awaitTermination (or look at the method signature) you will see it returns a boolean. This boolean indicates if the Executor terminated or not. You can use that information to create a while loop to determine if it has been terminated or not.
ExecutorService executor = ...
executor.shutdown(); // close the executor and don't accept new tasks
while (!executor.awaitTermination(100, TimeUnit.MILLISECONDS) {}
Something like this will stop the executor and wait until it terminated and all tasks have finished.
execute method does not return anything. You can use the submit method which returns a result of type Future.
Future<String> future =
executorService.submit(callableTask/runnableTask);
If you use class ThreadPoolExecutor or any of its children you have a method there getActiveCount() that returns the number of threads that are actively executing tasks. So you can poll that method until it gets to 0, which would mean that all tasks have been completed and no new tasks are currently executing. However, what if some task gets stuck? I think you will have to also give some timeout in order to prevent infinite loop in this case. The biggest advantage of this idea is that you are not required to invoke shutdown method
There are several approaches.
You can call first ExecutorService.shutdown and then ExecutorService.awaitTermination which returns:
true if this executor terminated and false if the timeout elapsed
before termination
So:
There is a function called awaitTermination But a timeout has to be
provided in it. Which is not a guarantee that when this returns all
the tasks would have been finished. Is there a way to achieve this ?
You just have to call awaitTermination in a loop.
Using awaitTermination
A full example with this implementation:
public class WaitForAllToEnd {
public static void main(String[] args) throws InterruptedException {
final int total_threads = 4;
ExecutorService executor = Executors.newFixedThreadPool(total_threads);
for(int i = 0; i < total_threads; i++){
executor.execute(parallelWork(100 + i * 100));
}
int count = 0;
// This is the relevant part
// Chose the delay most appropriate for your use case
executor.shutdown();
while (!executor.awaitTermination(100, TimeUnit.MILLISECONDS)) {
System.out.println("Waiting "+ count);
count++;
}
}
private static Runnable parallelWork(long sleepMillis) {
return () -> {
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
// Do Something
}
System.out.println("I am Thread : " + Thread.currentThread().getId());
};
}
}
Using CountDownLatch
Another option is to create a CountDownLatch with a count equals to the number of parallel tasks. Each thread calls countDownLatch.countDown();, while the main thread calls countDownLatch.await();.
A full example with this implementation:
public class WaitForAllToEnd {
public static void main(String[] args) throws InterruptedException {
final int total_threads = 4;
CountDownLatch countDownLatch = new CountDownLatch(total_threads);
ExecutorService executor = Executors.newFixedThreadPool(total_threads);
for(int i = 0; i < total_threads; i++){
executor.execute(parallelWork(100 + i * 100, countDownLatch));
}
countDownLatch.await();
System.out.println("Exit");
executor.shutdown();
}
private static Runnable parallelWork(long sleepMillis, CountDownLatch countDownLatch) {
return () -> {
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
// Do Something
}
System.out.println("I am Thread : " + Thread.currentThread().getId());
countDownLatch.countDown();
};
}
}
Using Cyclic Barrier
Another approach is to use a Cyclic Barrier
public class WaitForAllToEnd {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
final int total_threads = 4;
CyclicBarrier barrier = new CyclicBarrier(total_threads+ 1);
ExecutorService executor = Executors.newFixedThreadPool(total_threads);
for(int i = 0; i < total_threads; i++){
executor.execute(parallelWork(100 + i * 100, barrier));
}
barrier.await();
System.out.println("Exit");
executor.shutdown();
}
private static Runnable parallelWork(long sleepMillis, CyclicBarrier barrier) {
return () -> {
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
// Do Something
}
System.out.println("I am Thread : " + Thread.currentThread().getId());
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
// Do something
}
};
}
}
There are other approaches but those would require changes to your initial requirements, namely:
How to wait for all tasks to be completed when they are submitted
using ExecutorService.execute() .
I have loop that assign task to ExecutorService with fixed size thread, I want the main program wait for threadPool to free one of its' threads to assign another task to it.
Here is my sample code: in this sample code I want finished! be printed at end and want to use ExecutorService.
public static void main(String[] args) {
ExecutorService ex = Executors.newFixedThreadPool(3);
for(int i=0; i< 100; i++) {
ex.execute(new TestThread(i)); // I want the program wait here for at least one thread to free
}
System.out.println("finished!");
}
private static class TestThread implements Runnable {
private int i;
public TestThread(int i) {
this.i = i;
}
#Override
public void run() {
System.out.println("hi: " + i);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
I understand you want for the thread that is submitting a job, to block in the case when there is not a free, readily available worker thread in the executor service. This can be useful to apply back-pressure.
At the core the executor service is "simply" composed of a queue of runnables, and of a pool of worker threads.
You can obtain this behaviour by building an executor service with a work-queue of fixed size (in your case, size one).
In code: (note that, your caller thread will still continue after submitting the last job; it will not wait for that job to be completed)
package stackOv;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class BackPressure {
public static void main(String[] args) {
// this is the backing work queue; in this case, it is of bounded size
ArrayBlockingQueue<Runnable> q = new ArrayBlockingQueue<>(1);
ExecutorService ex = new ThreadPoolExecutor(3, 3, 30, TimeUnit.SECONDS, q,
new ThreadPoolExecutor.CallerRunsPolicy());
for(int i=0; i< 100; i++) {
ex.execute(new TestWork(i));
}
System.out.println("finished!");
}
private static class TestWork implements Runnable {
private int i;
public TestWork(int i) {
this.i = i;
}
#Override
public void run() {
System.out.println("hi: " + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
All you need is:
ex.awaitTermination();
I am trying to see if there anyway a single thread in Java can switch between tasks where each task is an infinite loop ?
I have the following code and I am wondering if there is any possible way I could make the count for all three jobs below change while they run on single thread? perhaps using wait/notify?
I was able to change the count only for one job but not for all three jobs.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Job implements Runnable {
protected int count;
public Job(){
this.count = 0;
}
public void run() {
System.out.println(Thread.currentThread().getName());
while(true) {
this.count = this.count + 1;
System.out.print("");
}
}
}
public class ThreadTest {
static int tasks = 3;
static Job[] jobs = new Job[3];
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(1);
for (int i = 0; i < tasks; i++) {
jobs[i] = new Job();
executor.execute(jobs[i]);
}
while (!executor.isTerminated()) {
for (int i = 0; i < tasks; i++) {
System.out.print(jobs[i].c + " ");
}
System.out.println();
try { Thread.sleep(1000); } catch (InterruptedException ex) { }
}
System.out.println("end");
}
}
The reason your current code doesn't work can be found in the documentation:
If additional tasks are submitted when all threads are active, they
will wait in the queue until a thread is available
Your first Job is running forever and so the other Jobs are never taken off the queue.
One way to solve this would be by having each Job add itself to the back of the queue once it's completed one iteration. This allows other items in the queue to be given time to execute:
class Job implements Runnable {
protected int count;
private final ExecutorService executor;
public Job(ExecutorService executor){
this.count = 0;
this.executor = executor;
}
public void run() {
System.out.println(Thread.currentThread().getName());
this.count = this.count + 1;
System.out.print("");
executor.execute(this);
}
}
And you'd need to change
new Job();
to
new Job(executor);
No: when a thread is allocated to a task, it executes the run() method. When the run method returns or when there is an exception, the next task will be allocated to the thread.
Below is my method in which I have single thread executor to execute some task in the run method.
private void trigger(final Packet packet) {
// this line is throwing exception
Executors.newSingleThreadExecutor().execute(new Runnable() {
#Override
public void run() {
// some code here
}
});
}
Below is the exception I am getting and I am not sure why? What is the best way to fix this?
error= java.util.concurrent.RejectedExecutionException: Task com.abc.stuffProc$2#e033da0 rejected from java.util.concurrent.ThreadPoolExecutor#76c2da8f[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2048)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:821)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1372)
at java.util.concurrent.Executors$DelegatedExecutorService.execute(Executors.java:628)
What happens if my trigger method is called many times and it is still working on the run method from my previous threads? Will it launch as many threads or it will wait for one thread to finish and then start another thread?
See here: What could be the cause of RejectedExecutionException
as you could see from the error log, your ThreadPoolExecutor is Terminated.
Maybe this is what you want:
private void trigger(final Packet packet) {
executor.execute(new Runnable() {
#Override
public void run() {
// some code here
}
});
}
private final ExecutorService executor = Executors.newFixedThreadPool(10);
EDIT Reproduce the Problem with:
public static void main(String[] args) {
final ExecutorTest et = new ExecutorTest();
for (int i = 0; i < 50000; i++) {
et.trigger(i);
}
System.out.println("Done");
}
private void trigger(int i) {
try {
Executors.newSingleThreadExecutor().execute(() -> {
try {
Thread.sleep(1000);
} catch (final InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
});
} catch (final Exception e) {
System.out.println("Test " + i + " with " + Thread.activeCount());
e.printStackTrace();
}
}
Create ThreadPoolExecutor outside of your trigger method. You should not create newSingleThreadExecutor for every call.
private ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private void trigger(final Packet packet) {
executorService .execute(new Runnable() {
#Override
public void run() {
// some code here
}
});
}
Regarding your exception, please check execute method description.
public void execute(Runnable command)
Executes the given task sometime in the future. The task may execute in a new thread or in an existing pooled thread. If the task cannot be submitted for execution, either because this executor has been shutdown or because its capacity has been reached, the task is handled by the current RejectedExecutionHandler.
Since it's unbounded queue, most likely you have called shutdown some where else in your code.
I currently have the following setup. I am getting out fo memory exceptions after it runs for a little while; I suspect the for loop in main is causing too much of a backup method calls. What is the best way to throttle the calls if I don't wish to increase the thread pool size?
public class ManagedThreads {
private final static ExecutorService ex = Executors.newFixedThreadPool(10);
public static void myMethod(final int i) {
ex.execute(new Runnable() {
public void run() {
// method body using i
}
});
}
public static void main(String[] args) {
for (int i = 0; i < 1000000000; ++i)
myMethod(i);
}
}
EDIT
I meant to show that I am passing in the index for the loop to the runnables.
You have ten threads so add ten jobs and you will never run out of memory trying to schedule them.
e.g.
public class ManagedThreads {
private final static ExecutorService ex = Executors.newFixedThreadPool(10);
public static void myMethod(final int i) {
ex.execute(new Runnable() {
public void run() {
// do every tenth task.
for(int j = i; j < 1000000000; j += 10) {
// method body
}
}
});
}
public static void main(String[] args) {
for (int i = 0; i < 10; ++i)
myMethod(i);
}
}
I am getting out fo memory exceptions after it runs for a little while; I suspect the for loop in main is causing too much of a backup method calls. What is the best way to throttle the calls if I don't wish to increase the thread pool size?
This is a FAQ. See my answer here: Process Large File for HTTP Calls in Java
You need to define your own bounded job queue and then define a RejectedExecutionHandler. The following code will block when it tries to add more than 100 jobs to the job queue.
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(100);
ThreadPoolExecutor threadPool =
new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, queue);
// we need our RejectedExecutionHandler to block if the queue is full
threadPool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
// this will block the producer until there's room in the queue
executor.getQueue().put(r);
} catch (InterruptedException e) {
throw new RejectedExecutionException(
"Unexpected InterruptedException", e);
}
}
});
i would go with this (it will allow each worker to perform same amount of work in terms of cpu clocks)
private final static ExecutorService ex = Executors.newFixedThreadPool(10);
final static AtomicInteger counter = new AtomicInteger(0);
public static void myMethod(final int i) {
ex.execute(new Runnable() {
public void run() {
while (counter.getAndIncrement() < 1000000000) {
//method body
}
}
});
}
public static void main(String[] args) {
for (int i = 0; i < 10; ++i)
myMethod(i);
}
}
or do increments of 10 in each worker as Peter suggested. Saves a lot of objects and processing speed is high.