Waiting on tasks from different Executors - java

I have certain logical operations separated into different tasks running concurrently on different java.util.concurrent.Executors.
For all tasks in an operation, I'd like to be notified once each one completes (i.e, a notification once all are done is not enough in this case).
Is there an implementation of java.util.concurrent.CompletionService which can wait and provide task results from more than one Executor? Would this even be possible?
My current (not perfect) solution is a queue of tasks being taken from the CompletionService by the order of their submission. A proprietary solution using listeners is also possible, though I would prefer to use java.util.concurrent if at all possible.
Edit: I eventually did as suggested by Greg except I extended FutureTask instead of Runnable.

You probably could just wrap your Executors with an entity that knows of the CompletionService's Queue.
i.e.
public class MyCompletionService implements Executor /* optional implements CompletionService too */ {
private final Executor mExecutor;
private Queue<Runnable> mRunnableQueue;
public MyNotifyingExecutorWrapper (Queue<Runnable> queueToNotify, Executor wrapped) {
mExecutor = wrapped;
mRunnableQueue = queueToNotify;
}
public execute(Runnable command) {
mExecutor.execute(new NotifyingRunnable(command, mRunnableQueue));
}
private static class NotifyingRunnable implements Runnable {
private final Queue<Runnable> mRunnables;
private Runnable mRunnable;
public NotifyingRunnable(Runnable runnable, Queue<Runnable> done) {
mRunnables = done;
mRunnable = runnable;
}
public void run() {
mRunnable.run();
mRunnables.add(mRunnable);
}
}
}
You could make this class implements CompletionExecutorService and choose one instance to take/poll from (assuming all your instances use the same queue), or just create a consumer of the queue in a more raw sense.
public static void main(String[] args) {
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue();
private MyCompletionService[] executors = ... {} ;
while(true){
System.out.println(String.format("%s: Woohoo %s is done!", System.currentTimeMillis(), queue.take()));
}
}
}
Note omitted Exception handling and actual implicit code of executing the individual tasks :)

Related

ExecutorService does not run tasks in parallel

I have a recursive bulk task that I put into execution in a ForkJoinPool thread pool.
public class SomeTask extends RecursiveAction {
#Override
protected void compute() {
//Some recursive logic...
}
}
public class Main {
public static void main(String[] args) {
startForkJoinPool();
}
private void startForkJoinPool() {
SomeTask someTask = new SomeTask();
ForkJoinPool pool = new ForkJoinPool(4);
pool.invoke(someTask);
pool.shutdown();
}
}
Now I need to execute this logic in two more parallel threads.
I decided to try to use the ExecutorService thread pool, and when I put entities into it for execution, I found out that they are not executed in parallel, but, as it were, one of the threads is parked for the duration of the first one.
public class SomeTask extends RecursiveAction {
#Override
protected void compute() {
//Some recursive logic...
}
}
public class Main {
public static void main(String[] args) {
List<Thread> threadList = new ArrayList<>();
threadList.add(new Thread(() -> startForkJoinPool()));
threadList.add(new Thread(() -> startForkJoinPool()));
ExecutorService executorService = Executors.newFixedThreadPool(2);
threadList.forEach(executorService::execute);
executorService.shutdown();
}
private void startForkJoinPool() {
SomeTask someTask = new SomeTask();
ForkJoinPool pool = new ForkJoinPool(4);
pool.invoke(someTask);
pool.shutdown();
}
}
Tell me, please, what can I do wrong?
Many thanks in advance to anyone who can point me in the right direction.
It is a bit strange that your code example contains ExecutorService.invoke and ExecutorService.execute where you should be calling ExecutorService.submit.
The ExecutorService documentation also contains a usage example.
And then there is some nice Java Tutorial on the topic.
Don't create any threads, that is the job of the ExecutorService.
You don't want to execute the task, you want to submit the task. Then you get a Future<T> returned.
As you already have a collection, consider invokeAll that returns List<Future<T>> and saves you iterating through your list.
tl;dr
Change execute to submit.
Await termination when shutting down an executor service.
Executor#execute is not necessarily async
You need to carefully read the documentation. This is a tricky area.
The ExecutorService#execute method is inherited from the super interface Executor.
The Javadoc for Executor says:
However, the Executor interface does not strictly require that execution be asynchronous
So any Runnable you pass to execute may or may not be run on a background thread.
ExecutorService#submit is always async
If you definitely want your Runnable to run on a background thread, pass to ExecutorService#submit.
Change this line:
threadList.forEach(executorService::execute);
… to this:
threadList.forEach(executorService::submit);
Shutdown
Your call to ExecutorService#shutdown is insufficient. You need to wait for submitted tasks to complete.
See the boilerplate method shutdownAndAwaitTermination given to you in the Javadoc for ExecutorService.
Or, in Java 19+, call ExecutorService#close.

How to manage threads in Spring TaskExecutor framework

I have a BlockingQueue of Runnable - I can simply execute all tasks using one of TaskExecutor implementations, and all will be run in parallel.
However some Runnable depends on others, it means they need to wait when Runnable finish, then they can be executed.
Rule is quite simple: every Runnable has a code. Two Runnable with the same code cannot be run simultanously, but if the code differ they should be run in parallel.
In other words all running Runnable need to have different code, all "duplicates" should wait.
The problem is that there's no event/method/whatsoever when thread ends.
I can built such notification into every Runnable, but I don't like this approach, because it will be done just before thread ends, not after it's ended
java.util.concurrent.ThreadPoolExecutor has method afterExecute, but it needs to be implemented - Spring use only default implementation, and this method is ignored.
Even if I do that, it's getting complicated, because I need to track two additional collections: with Runnables already executing (no implementation gives access to this information) and with those postponed because they have duplicated code.
I like the BlockingQueue approach because there's no polling, thread simply activate when something new is in the queue. But maybe there's a better approach to manage such dependencies between Runnables, so I should give up with BlockingQueue and use different strategy?
If the number of different codes is not that large, the approach with a separate single thread executor for each possible code, offered by BarrySW19, is fine.
If the whole number of threads become unacceptable, then, instead of single thread executor, we can use an actor (from Akka or another similar library):
public class WorkerActor extends UntypedActor {
public void onReceive(Object message) {
if (message instanceof Runnable) {
Runnable work = (Runnable) message;
work.run();
} else {
// report an error
}
}
}
As in the original solution, ActorRefs for WorkerActors are collected in a HashMap. When an ActorRef workerActorRef corresponding to the given code is obtained (retrieved or created), the Runnable job is submitted to execution with workerActorRef.tell(job).
If you don't want to have a dependency to the actor library, you can program WorkerActor from scratch:
public class WorkerActor implements Runnable, Executor {
Executor executor=ForkJoinPool.commonPool(); // or can by assigned in constructor
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueu<>();
boolean running = false;
public synchronized void execute(Runnable job) {
queue.put(job);
if (!running) {
executor.execute(this); // execute this worker, not job!
running=true;
}
public void run() {
for (;;) {
Runnable work=null;
synchronized (this) {
work = queue.poll();
if (work==null) {
running = false;
return;
}
}
work.run();
}
}
}
When a WorkerActor worker corresponding to the given code is obtained (retrieved or created), the Runnable job is submitted to execution with worker.execute(job).
One alternate strategy which springs to mind is to have a separate single thread executor for each possible code. Then, when you want to submit a new Runnable you simply lookup the correct executor to use for its code and submit the job.
This may, or may not be a good solution depending on how many different codes you have. The main thing to consider would be that the number of concurrent threads running could be as high as the number of different codes you have. If you have many different codes this could be a problem.
Of course, you could use a Semaphore to restrict the number of concurrently running jobs; you would still create one thread per code, but only a limited number could actually execute at the same time. For example, this would serialise jobs by code, allowing up to three different codes to run concurrently:
public class MultiPoolExecutor {
private final Semaphore semaphore = new Semaphore(3);
private final ConcurrentMap<String, ExecutorService> serviceMap
= new ConcurrentHashMap<>();
public void submit(String code, Runnable job) {
ExecutorService executorService = serviceMap.computeIfAbsent(
code, (k) -> Executors.newSingleThreadExecutor());
executorService.submit(() -> {
semaphore.acquireUninterruptibly();
try {
job.run();
} finally {
semaphore.release();
}
});
}
}
Another approach would be to modify the Runnable to release a lock and check for jobs which could be run upon completion (so avoiding polling) - something like this example, which keeps all the jobs in a list until they can be submitted. The boolean latch ensures only one job for each code has been submitted to the thread pool at any one time. Whenever a new job arrives or a running one completes the code checks again for new jobs which can be submitted (the CodedRunnable is simply an extension of Runnable which has a code property).
public class SubmissionService {
private final ExecutorService executorService = Executors.newFixedThreadPool(5);
private final ConcurrentMap<String, AtomicBoolean> locks = new ConcurrentHashMap<>();
private final List<CodedRunnable> jobs = new ArrayList<>();
public void submit(CodedRunnable codedRunnable) {
synchronized (jobs) {
jobs.add(codedRunnable);
}
submitWaitingJobs();
}
private void submitWaitingJobs() {
synchronized (jobs) {
for(Iterator<CodedRunnable> iter = jobs.iterator(); iter.hasNext(); ) {
CodedRunnable nextJob = iter.next();
AtomicBoolean latch = locks.computeIfAbsent(
nextJob.getCode(), (k) -> new AtomicBoolean(false));
if(latch.compareAndSet(false, true)) {
iter.remove();
executorService.submit(() -> {
try {
nextJob.run();
} finally {
latch.set(false);
submitWaitingJobs();
}
});
}
}
}
}
}
The downside of this approach is that the code needs to scan through the entire list of waiting jobs after each task completes. Of course, you could make this more efficient - a completing task would actually only need to check for other jobs with the same code, so the jobs could be stored in a Map<String, List<Runnable>> structure instead to allow for faster processing.

How to Manage Queue of Runnable Tasks in Android

I have multiple tasks/Runnable (i.e. downloading images from internet), which are generated as the user scrolls through a list in a Android App.
I cannot control how many tasks/Runnable are generated at a time, this could in 100. But I want to execute only n(10) tasks in parallel. So, I am planning to build a design, where as soon as a new task/runnable is generated, it will be added to a queue (List<Runnable>) and through Executors.newFixedThreadPool(10), I will execute only first 10 runnable tasks in parallel. Now as soon as the tasks/Runnable are completed, I should be able to remove them from queue (List<Runnable>) and should be able to execute new tasks/Runnable which are in queue, in FIFO.
I have two classes for this design. First is ExecutorManager which is a singleton class and manages the executions of 10 parallels tasks and second is the ImageDownloader class which implements runnable and is responsible to download the image. I am not sure what is the best way to inform the ExecutorManager that the task/download is completed and it can execute new task from the queue. I am following FIFO, so I will always start execution from first 10 tasks in the queue, but how will I get to know, which task is completed and which one to remove from the Queue?
public class ImageDownloader implements Runnable{
DownloadListener mDownloadListener;
public ImageDownloader(DownloadListener mDownloadListener, String URL){
this.mDownloadListener = mDownloadListener;
}
#Override
public void run() {
//Download the Image from Internet
//ToDo
//if Success in download
mDownloadListener.onDownloadComplete();
//if Error in download
mDownloadListener.onDownloadFailure();
//Inform the Executor Manager that the task is complete and it can start new task
incrementCount();
}
private static synchronized void incrementCount(){
ExecutorManager.getInstance().OnTaskCompleted();// is there a better way to do it
}
}
public class ExecutorManager {
private static ExecutorManager Instance;
ExecutorService executor = Executors.newFixedThreadPool(Constants.NumberOfParallelThread);
ArrayList<Runnable> ExecutorQueue = new ArrayList<Runnable>();
int ActiveNumberOfThread = 0;
private ExecutorManager(){
}
public static ExecutorManager getInstance(){
if(Instance==null){
Instance = new ExecutorManager();
}
return Instance;
}
private void executeTask(){
if(ExecutorQueue.size()>0 && ActiveNumberOfThread < Constants.NumberOfParallelThread){
++ActiveNumberOfThread;
executor.execute(ExecutorQueue.get(0));//Execute the First Task in Queue
}
}
public void enQueueTask(Runnable Task){
ExecutorQueue.add(Task);
executeTask();
}
public void removeFromQueue(){
//How to know, which task to remove?
ExecutorQueue.remove(0);
}
public void OnTaskCompleted(){
--ActiveNumberOfThread;
removeFromQueue();
executeTask();
}
}
Well, you're in luck. You don't have to tell the ExecutorManager anything at all. An ExecutorService with a BlockingQueue handles queues for you. All you have to do is submit the Runnable to the ExecutorService. It will hold on to it. If there are any open threads, it will run it instantly. Else, it will wait until one of the other Runnables finishes execution. Once it finishes, it will take the next one.
If you look at the source code for Executors#newFixedThreadPool, it actually just creates a ThreadPoolExecutor with nThreads threads backed by a LinkedBlockingQueue like so:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

Using concurrent classes to process files in a directory in parallel

I am trying to figure out how to use the types from the java.util.concurrent package to parallelize processing of all the files in a directory.
I am familiar with the multiprocessing package in Python, which is very simple to use, so ideally I am looking for something similar:
public interface FictionalFunctor<T>{
void handle(T arg);
}
public class FictionalThreadPool {
public FictionalThreadPool(int threadCount){
...
}
public <T> FictionalThreadPoolMapResult<T> map(FictionalFunctor<T> functor, List<T> args){
// Executes the given functor on each and every arg from args in parallel. Returns, when
// all the parallel branches return.
// FictionalThreadPoolMapResult allows to abort the whole mapping process, at the least.
}
}
dir = getDirectoryToProcess();
pool = new FictionalThreadPool(10); // 10 threads in the pool
pool.map(new FictionalFunctor<File>(){
#Override
public void handle(File file){
// process the file
}
}, dir.listFiles());
I have a feeling that the types in java.util.concurrent allow me to do something similar, but I have absolutely no idea where to start.
Any ideas?
Thanks.
EDIT 1
Following the advices given in the answers, I have written something like this:
public void processAllFiles() throws IOException {
ExecutorService exec = Executors.newFixedThreadPool(6);
BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<Runnable>(5); // Figured we can keep the contents of 6 files simultaneously.
exec.submit(new MyCoordinator(exec, tasks));
for (File file : dir.listFiles(getMyFilter()) {
try {
tasks.add(new MyTask(file));
} catch (IOException exc) {
System.err.println(String.format("Failed to read %s - %s", file.getName(), exc.getMessage()));
}
}
}
public class MyTask implements Runnable {
private final byte[] m_buffer;
private final String m_name;
public MyTask(File file) throws IOException {
m_name = file.getName();
m_buffer = Files.toByteArray(file);
}
#Override
public void run() {
// Process the file contents
}
}
private class MyCoordinator implements Runnable {
private final ExecutorService m_exec;
private final BlockingQueue<Runnable> m_tasks;
public MyCoordinator(ExecutorService exec, BlockingQueue<Runnable> tasks) {
m_exec = exec;
m_tasks = tasks;
}
#Override
public void run() {
while (true) {
Runnable task = m_tasks.remove();
m_exec.submit(task);
}
}
}
How I thought the code works is:
The files are read one after another.
A file contents are saved in a dedicated MyTask instance.
A blocking queue with the capacity of 5 to hold the tasks. I count on the ability of the server to keep the contents of at most 6 files at one time - 5 in the queue and another fully initialized task waiting to enter the queue.
A special MyCoordinator task fetches the file tasks from the queue and dispatches them to the same pool.
OK, so there is a bug - more than 6 tasks can be created. Some will be submitted, even though all the pool threads are busy. I've planned to solve it later.
The problem is that it does not work at all. The MyCoordinator thread blocks on the first remove - this is fine. But it never unblocks, even though new tasks were placed in the queue. Can anyone tell me what am I doing wrong?
The thread pool you are looking for is the ExecutorService class. You can create a fixed-size thread pool using newFixedThreadPool. This allows you to easily implement a producer-consumer pattern, with the pool encapsulating all the queue and worker functionality for you:
ExecutorService exec = Executors.newFixedThreadPool(10);
You can then submit tasks in the form of objects whose type implements Runnable (or Callable if you want to also get a result):
class ThreadTask implements Runnable {
public void run() {
// task code
}
}
...
exec.submit(new ThreadTask());
// alternatively, using an anonymous type
exec.submit(new Runnable() {
public void run() {
// task code
}
});
A big word of advice on processing multiple files in parallel: if you have a single mechanical disk holding the files it's wise to use a single thread to read them one-by-one and submit each file to a thread pool task as above, for processing. Do not do the actual reading in parallel as it will degrade performance.
A simpler solution than using ExecuterService is to implement your own producer-consumer scheme. Have a thread that create tasks and submits to a LinkedBlockingQueue or ArrayBlockingQueue and have worker threads that check this queue to retrieve the tasks and do them. You may need a special kind of tasks name ExitTask that forces the workers to exit. So at the end of the jobs if you have n workers you need to add n ExitTasks into the queue.
Basically, what #Tudor said, use an ExecutorService, but I wanted to expand on his code and I always feel strange editing other people's posts. Here's a sksleton of what you would submit to the ExecutorService:
public class MyFileTask implements Runnable {
final File fileToProcess;
public MyFileTask(File file) {
fileToProcess = file;
}
public void run() {
// your code goes here, e.g.
handle(fileToProcess);
// if you prefer, implement Callable instead
}
}
See also my blog post here for some more details if you get stuck
Since processing Files often leads to IOExceptions, I'd prefer a Callable (which can throw a checked Exception) to a Runnable, but YMMV.

Are there any executor in java concurrent package which guarantee that all tasks will be done in order they were submitted?

A code sample for demonstration of the idea from the title:
executor.submit(runnable1);
executor.submit(runnable2);
I need to be sure that runnable1 will finish before runnable2 start and I haven't found any proofs of such behavior in the executors documentation.
About the problem I'm solving:
I need write lots of logs to a file. Each log requires much precomputing (formatting and some other stuff). So, I want to put each logging task to a kind of queue and process these tasks in a separate thread. And, of course, it's important to keep logs ordering.
A single threaded executor will perform all tasks in the order submitted. You would only use a thread pool with multiple threads if you wanted the tasks to be perform concurrently.
Adding tasks to a queue can be expensive in itself. You can use an Exchanger like this
http://vanillajava.blogspot.com/2011/09/exchange-and-gc-less-java.html?z#!/2011/09/exchange-and-gc-less-java.html
This avoid using a queue or creating object.
An alternative which is faster is to use a memory mapped file which doesn't require a background thread (actually the OS is working in the background) This is much faster again. It supports sub-microsecond latencies and millions of messages per second.
https://github.com/peter-lawrey/Java-Chronicle
You could create a simple wrapper like the one below so that all your Runnables are executed in the same thread (i.e. sequentially), and submit that wrapper to the executor instead. That does not address the logging issue.
class MyRunnable implements Runnable {
private List<Runnable> runnables = new ArrayList<>();
public void add(Runnable r) {
runnables.add(r);
}
#Override
public void run() {
for (Runnable r : runnables) {
r.run();
}
}
}
//......
MyRunnable r = new MyRunnable();
r.add(runnable1);
r.add(runnable2);
executor.submit(r);
Presumably you are doing some post-analysis of the logfile? Have you considered not caring about the order they're written and re-ordering offline later. You could allocate a unique id at submit time using, a timestamp or AtomicLong?
a code sketch (untested) would look like this:
import java.util.concurrent.atomic.AtomicLong;
class MyProcessor {
public void work()
for (Object data: allData) {
executor.submit(new MySequencedRunnable(data);
}
}
}
class MySequencedRunnable implements Runnable {
private static final AtomicLong LOG_SEQUENCE_ID = new AtomicLong(0);
private final Object data;
MySequencedRunnable(Object data) {
this.data = data;
}
public void run() {
LOGGER.log(LOG_SEQUENCE_ID.incrementAndGet(), data);
}
}
Also consider, if you're using something like log4j, using NDC or MDC to assist with the re-ordering.

Categories