Can a nested ExecutorService run in parallel - java

Edit: Changed the title and reformatted my code: (Pleas bear with my questions, i am new to this parallel world)
Instead of using FJPool, i am using ExecutorService now to parallelize my tasks. All tasks and subtasks are independent and can run in parallel without any conflict. Here is my code snippet:
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> someTask(args1);
executor.submit(() -> someTask(args2);
// Wait for tasks to complete and shutdown executor
private static void someTask( ... ) {
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// executor runs a bunch of tasks in parallel here and then shutdown executor
}
My question is if i need to adjust number of thread pool since 2 tasks running in parallel try to create thread pool of the size of # of available cores? Will this work or will this block one of the initial task until we release the threads by shutting down?
===== Initial question =====
My question is slightly different that this question.
I have 2 tasks, someTask1 and someTask2 which i am planning to parallelize. The problem is (i am not sure if this could be a problem or not) that someTask1 uses ForkJoinPool and runs a bunch of other tasks in parallel. Can I parallelize the 2 tasks someTask1 and someTask2 using ForkPoolJoin something like the code below even though one of the task i am parallelizing runs other tasks in parallel? If its possible can i get some help on refactoring the code below:
ForkPoolJoin forkJoinPool = new ForkJoinPool(parallelism);
if (someCond1) {
forkJoinPool.submit(() -> someTask1( ... ));
}
if (someCond2) {
forkJoinPool.submit(() -> someTask2( ... ));
}
// I want to wait here until forkJoinPool is done with both tasks (or either of the 1 based on each condition)?
private void someTask1( ... ) {
ForkPoolJoin forkJoinPool = new ForkJoinPool(parallelism);
try {
forkJoinPool.submit(() -> someStream.stream().map( ... ))
.get(); // Wait for all the tasks to complete
} finally {
forkJoinPool.shutdown();
}
}
Edit:
I figured out a way to deal with the waiting issue. My solution is since i only have 2 tasks in parallel, i store the result of the forkJoinPool.submit into 2 Future variables and call on their get() function one by one. If someone else has a better more generic solution, that would be great.

Related

Java Executors cancel job by timeout with inner executor

I have a big thread pool like
ThreadPoolExecutor pool = new ThreadPoolExecutor(cores, 50, 30L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3000));
I want to submit a task there. But I don't want to call future.get() at all, I want to submit it and forget.
But, I want my task to be cancelled in a certain time period. So I do the following:
public void run(){
FutureTask<WorkerWrapper> task = new FutureTask<>(()->worker.process(tmpArg));
executor.execute(task);
res=task.get(2, TimeUnit.MINUTES);
executor.shutdown();
}
In other words, I call executor inside executor. Is it safe and stable? Or can I cancel my task by timeout other way?
The only real way to achieve this, AFAIK, is to have a second ScheduledExecutor. You'd still need a handle of the Future but only pass it to the scheduled executor for cancellation.
Future<WorkedWrapper> task = executor.execute(() -> worker.process(tmpArg));
scheduledExecutor.schedule(() -> task.cancel(true), 2, TimeUnit.MINUTES);
There may be a more fluent way of handling this with CompleteableFutures but I am not 100% sure of that.
ScheduledThreadPoolExecutor has a method that allows to to schedule a runnable and get a future back. You can combine this with the timed get on the future:
ScheduedThreadPoolExecutor e = ...
Future<T> f = e.submit(new Runnable(){..},new T(){});
Object ignore = f.get(timeout, timeunit);

Use ExecutorService or Similar to Queue Tasks to be Completed in Order?

Let's say I have three tasks: download .zip from internet, unzip file, then swap out a local file with the unzipped file. I can't block the main thread, as it's being used by the server, but I need these three tasks to complete in order. Is there a way to use ExecutorService or something similar to queue these tasks so that one completes after the other without blocking on the main thread?
You can use a single thread executor. The services below will run in parallel to the main thread, and the three tasks handled by e2 will run sequentially.
ExecutorService e1 = Executors.newSingleThreadExecutor();
ExecutorService e2 = Executors.newSingleThreadExecutor();
e1.execute( new ExpressTask() );
e2.execute( new SequentialTask("Part-One"));
e2.execute( new SequentialTask("Part-Two"));
e2.execute( new SequentialTask("Part-Three"));
e1.shutdown();
e2.shutdown();
Just run a thread:
new Thread() {
public void run() {
task1.run();
task2.run();
task3.run();
}
}.start();

Schedule multiple tasks on multiple threads

I need to perform some data collection periodically, for that I want to create a task which requests some data from different servers. Some servers will take more time to process the request and return the response than others.
That's why I want to create a task for each server and execute the tasks async. If i'm using ScheduledExecutorService in the following way will each task execute in its own thread or all the tasks will be executed in the same thread?
What happens if a task is throwing an exception all the other scheduled tasks will fail?
this.scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
return new Thread(r, "collectionThread");
}
});
for (String url:urls){
this.scheduler.scheduleWithFixedDelay(new CollectorTask(url),
startupDelaySeconds,
scheduleRateSeconds,
TimeUnit.SECONDS);
}
You're using a single-threaded executor service, so all tasks are being executed sequentially. If any of them throws an exception, all next tasks executions are cancelled.
You could use
Executors.newScheduledThreadPool(4) // 4 is the max number of parallel jobs
... to allow parallel execution and wrap a body of a submitted job into
try {
...
} catch(Exception e){
logger.warn("exception during task execution", e);
}
to log errors without propagating them.
Minor delays (several milliseconds) are possible and depend on the OS, tasks will never execute earlier than their scheduled time. Task's execution can be delayed due to previous long runs or lack of free threads, but the following executions will be run by the original schedule: initialDelay + n * period.
Yes, what you do is create two thread executors. The first is a scheduled executor which takes a runnable that is meant to start your actual runnable. All this runnable does it create an instance of your task runnable and submit it to the real executor. That executor should just be a normal thread pool that will handle the tasks.
private final ScheduledExecutorService scheduledExecutor = Executors
.newSingleThreadScheduledExecutor();
private final ExecutorService executor = Executors.newCachedThreadPool();
private class SubmitTaskRunnable implements Runnable {
#Override
public void run() {
executor.execute(new TaskRunnable());
}
}
Schedule the SubmitTaskRunnable on your scheduled executor because that one will not throw any exceptions. Let your actual task run inside a cached executor will allow multiple tasks to run concurrently even if the previous ones have not finished.

How to identify when all tasks in pipeline have completed within single Java Executor Service

I have a pipeline of tasks to be done on files, each different type of task runs inside a different executor service. After initilizing each executor service I start the first task, this is guaranteed to not finish until finished processing all files, as it processes a folder either no more work is required or its submits a callable task to service2. So when the shutdown() call on first task is sucessful all files will now be being processed in task2 or a another task further down the pipleline, and so on. When we can shutdown the final service then we have finished.
Loader loader = Loader.getInstanceOf();
List<ExecutorService> services = new ArrayList<ExecutorService>();
ExecutorService es = Executors.newSingleThreadExecutor();
//Init Services
services.add(es);
services.add(task1.getService());
services.add(task2.getService());
services.add(task3.getService());
services.add(task4.getService());
//Start Loading Files
es.submit(loader);
int count = 0;
for (ExecutorService service : services)
{
service.shutdown();
count++;
//Now wait for all submitted tasks to complete, for upto one day per task
service.awaitTermination(10, TimeUnit.DAYS);
MainWindow.logger.severe("Shutdown Task:" + count);
}
public class AnalyserService
{
protected String threadGroup;
public AnalyserService(String threadGroup)
{
this.threadGroup=threadGroup;
}
protected ExecutorService executorService;
protected CompletionService completionService;
protected void initExecutorService()
{
int workerSize = Runtime.getRuntime().availableProcessors();
executorService
= Executors.newFixedThreadPool(workerSize, new SongKongThreadFactory(threadGroup));
}
public ExecutorService getService()
{
if (executorService == null || executorService.isShutdown())
{
initExecutorService();
}
return executorService;
}
}
So this is all working fine Except Ive got my cpu load logic incorrect. Every service uses a pool equal to the number of cpus the computer has. So if computer has 4 cpus and we have 5 services then we could have 20 threads all trying to work at the same time overloading the cpus. I think I should in this case only have 4 threads at a time.
If I limited each service to use one thread then Id only have 5 threads runningat same time, but this still isnt right because
Will no longer be right if have more services or more cpus
Is inefficient, as the pipleline kicks of most of the work will be done by task1 , if I limit it to one cpu it will be slower than neccessary, conversly later on most of the threads will be done by later tasks and task1 will have nothing to do.
I think what I need is for all tasks to share one executor service, and set its poolsize equal to the number of cput the computer has. But then how am I going to identify when the service has finished ?
Im using Java 7, so is there anything in new in Java 7 that may help, currently just using Java 5 concurrency features
The core of your problem is: "[...] overloading the cpus."
If this is the problem, just schedule the priority of your application correctly. By the way, you are more likely to increase IO load than to increase CPU load; a lot of different threads is actually a good thing :-)
However, your question is: " But then how am I going to identify when the service has finished ? "
Very simple answer: submit() instead of invokeAll() and check the isDone() method of the Future object you receive.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#submit(java.util.concurrent.Callable)

Multiple executor tasks notify master on completed?

I'm using a Java executor to divide and process a given task in parallel. There could be any number of tasks. They are all queued at the beginning and the master controller object simply waits for all of them to finish.
The problem I'm running into is how to determine when all tasks have been completed. Since one large task is only every queued at a single time (i.e. all currently queued tasks all belong to the same master task) I can use the getCompletedTaskCount() method to compare the number of completed tasks to the number of the number of tasks originally queued.
However, this requires that I constantly poll the executor for the number of completed tasks and in my opinion isn't that great of a solution.
while (pool.getCompletedTaskCount() - start_count < num_tasks)
{
try
{
Thread.sleep(30);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I thought about having a counter object which each task could increment, then if the count is equivalent to the number of expected tasks notify the master thread. Something like this (ignore the somewhat incomplete code like missing exception handlers and such):
Master thread:
counter_object.expected_count = num_tasks;
counter_object.count = 0;
queue_tasks();
synchronized(counter_object)
{
counter_object.wait();
}
// all tasks have finished
Worker tasks:
// ...do task
// task finished, update counter
synchronized(counter_object)
{
++counter_object.count;
if(counter_object.count == counter_object.expected_count)
{
// all tasks have finished, notify master thread
counter_object.notify();
}
}
This method also has the added benefit that I can use a single executor to run multiple master tasks since the counter object would be local to a given master.
Is there a better way to solve this problem? The number of tasks might very well be larger than the max number of threads the executor is allowed to create so I don't think a CyclicBarrier would work.
This sounds like a job of ExecutorService.invokeAll.
Collection<Callable> tasks = <get all sub tasks>;
executorService.invokeAll(tasks);
// Execution proceeds at the following line only once all "tasks" have been run
Alternatively (since you are likely dealing with Runnable instances and not Callable, you can use ExecutorService.submit(Runnable) and then wait for them to complete.
for (Runnable task:tasks) {
futures.add(executorService.submit(task));
}
for (Future<Void> result:futures) {
result.get();
}
Note: exception handling omitted

Categories