Is there an ExecutorService that will allow me to submit tasks without beginning execution until I request it? I'm looking for something like ScheduledExecutorService, except that I want to trigger the execution manually without depending on a fixed time delay.
The reason I'm looking for this is because I want to create a set of tasks which may recursively use results of Futures generated from parallel tasks in the same set. So I would need to first submit all the tasks in order to get a set of Futures, and only then could I allow the tasks to begin executing.
It sounds like a job for CompletableFuture
fire execution of first portion of tasks as separe CompletableFutures
then using CompletableFuture.allOf(...furures) to create a barrier future that completes only when all are done
then using one of combinators like CompletableFuture.thenAccept to schedule next portion of tasks to perform on completion of barrier future
But more idiomatic way to use it would be to chain each next task based on future result of some previous one
CompletableFuture<FirstResult> firstTask = //....
CompletableFuture<SecondResult> secondTask = firstTask.thenApply(someTransformation);
CompletableFuture<Void> anotherTaks = firstTask.thenAccept(someConsumer);
CompletableFuture<ThirdResult> combined = firstTask.thenAcceptBoth(secondTask, someFunction);
Perhaps an alternate approach would be to simply use a FutureCallback or an AsyncFunction?
FutureCallback example:
final List<ListenableFuture<T>> futures = new ArrayList<ListenableFuture<T>>();
final Callable<T> callable = new Callable<T>() {
// Some task you want to complete
};
// Submit all your tasks for execution
futures.add(listeningExecutorService.submit(callable));
// ... add as many tasks as you have
futures.add(listeningExecutorService.submit(callable));
// Get a single Future to wait on
final ListenableFuture<List<T>> future = Futures.allAsList(futures);
Futures.addCallback(future, new FutureCallback<List<T>>() {
#Override
public void onSuccess(final List<T> result) {
// Begin other tasks using `result` (the set of results from the first tasks)
}
#Override
public void onFailure(final Throwable t) {
// ...
}
});
This would be helpful if you don't care about waiting around for the second set of tasks to complete, as Futures.addCallback doesn't return anything.
AsyncFunction example:
final ListenableFuture<O> result = Futures.transform(future, new AsyncFunction<List<T>, O>() {
#Override
public ListenableFuture<O> apply(final List<T> input) {
// Begin other tasks using `input` (the set of results from the first tasks)
}
});
This would be beneficial if you want to wait on the resulting ListenableFuture, or potentially add a third set of tasks that need to happen upon completion of the second set.
Related
I have N tasks to execute, and the number of tasks is not fixed. The next task can only be executed after the previous task is completed. How can the entire task chain be executed asynchronously?
If the number of tasks is fixed, such as N=2, I can use the following code. How to do it if N is not fixed
public void futureTest() throws InterruptedException {
CompletableFuture<Integer> finalFuture = new CompletableFuture<>();
CompletableFuture<Integer> cf1 = doTask(1);
AtomicReference<CompletableFuture<Integer>> cf2 = new AtomicReference<>(new CompletableFuture<>());
cf1.whenComplete(((integer1, throwable1) -> {
if (throwable1 != null) {
finalFuture.completeExceptionally(throwable1);
return;
}
// when task1 complete then submit task2
cf2.set(doTask(2));
cf2.get().whenComplete(((integer2, throwable2) -> {
if (throwable2 != null) {
finalFuture.completeExceptionally(throwable2);
return;
}
finalFuture.complete(integer2);
}));
}));
finalFuture.whenComplete(((integer, throwable) -> {
System.out.println("all task is done");
}));
Thread.sleep(1000000);
}
private CompletableFuture<Integer> doTask(int index) {
CompletableFuture<Integer> cf = new CompletableFuture<>();
// Simulate task execution
THREAD_POOL.execute(() -> {
Thread.sleep(3_000);
cf.complete(index);
});
return cf;
}
I looked at Compeltable's API docs and none of them seem to solve my problem. I tried to use a loop to control the task submission, but all failed, unable to submit the next task after the previous task is completed
Refer to this answer on this thread Click here. Seems a duplicate of this question.
thenRun method is used to run the task after the previous future is completed successfully. This method will be skipped in case of any failures in previous stages.
whenComplete method is used as the final stage of execution chain. Here you will receive the composed result of all the other functions in the supply chain and you can choose to fail your future or handle exceptions accordingly inside this.
You can compose the futures for the individual tasks via CompletableFuture#thenCompose in a loop:
CompletableFuture<?> future = createFirstTask();
while (hasMoreTasks()) {
future = future.thenCompose(this::createNextTask);
}
Here every next tasks depends on the result of the previous one until no more task is left.
Conceptionally this is a fold operation, which unfortunately is not part of the API of CompletableFuture. But if you don't mind using my better future library (which is just a thin wrapper around CompleteableFuture), I just recently added support for folding streams of futures there.
I have a set of jobs which I am submitting using executor framework and Future. Let's say that I have 100 futures. As of now, I am using Future.get and using the output for subsequent processing. However for further tuning, I want to change the flow as below:
iterate through the set of future tasks and start consuming the result as soon as a future task is complete. I am reading the API doc to understand what might be a good way to accomplish this but reaching out to see if there is a better way to accomplish what I am looking for.
Here is the sample code:
public class ImplCallable implements Callable<String> {
int timeOut;
ImplCallable(int timeOut) {
this.timeOut=timeOut;
}
public String call() throws Exception {
Thread.sleep(timeOut);
return Thread.currentThread().getName();
}
}
and the main class:
public class MainProg {
public static void main(String...args) throws Exception {
long startTimeInMillis = System.currentTimeMillis();
ImplCallable callable1 = new ImplCallable(1000);
ImplCallable callable2 = new ImplCallable(2000);
ExecutorService service = Executors.newFixedThreadPool(4);
Future<String> task1 = service.submit(callable1);
Future<String> task2 = service.submit(callable2);
List<Future<String>> futureList = new ArrayList();
futureList.add(task1);
futureList.add(task2);
String retVal;
for(Future<String> task:futureList) {
retVal = task.get();
//do something with the retVal
}
long endTimeInMillis = System.currentTimeMillis();
System.out.println("time taken by code - " + (endTimeInMillis-startTimeInMillis) + "-ms");
}
}
Basically I don't want to use Future.get() and wait for its completion. I want to know if either of the task is complete and use the result as soon as its done.
There are many ways do this so, without a concrete example, you won't get a concrete answer. Likely want to look at CompletableFuture which has many methods for defining follow-on work, combining work, splitting work etc.
Future<String> f = CompletableFuture.supplyAsync(() -> "INITIAL WORK")
.thenApply(String::toLowerCase) // Do some more work
.thenAccept(queue::add); // put results onto a queue something is reading from
f.join();
// Batch complete
I hope you are using Java 8 or later version.
Whenever you mention "as soon as a future task is complete", you want to use CompletableFuture and its .thenApply() method, as #drekbour suggests.
Then you have multiple threads running different tasks in non-determenistic sequence. But at the end you want to get all the results in the single (Main) thread. To achieve it, you can use CompletableFuture.allOf method, .join() it - and then iterate over all the (already completed) future results without waiting.
I was developing a JavaFX app and I was supplying the JavaFX tasks in an ExecutorService submit method. Also I was trying to get the return value of the Task in the return value of the submit in a Future object. Then I discovered that ExecutorService only returns value when you submit a Callable object, and JavaFX Tasks are runnables despite having a call method. so is there any workaround for this problem?
I tried and solved my problem this way but I'm open to suggestions when I don't want to write my own class.
My main method:
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Semaphore semaphore = new Semaphore(1);
List<Integer> list = IntStream.range(0,100).boxed().collect(Collectors.toList());
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
List<Integer> sendingList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
sendingList.add(iterator.next());
}
System.out.println("SUBMITTING");
Future<Integer> future = executorService.submit((Callable<Integer>) new TestCallable(sendingList,semaphore));
System.out.println(future.get());
semaphore.acquire();
}
executorService.shutdown();
System.out.println("COMPLETED");
}
My TestCallable class:
class TestCallable extends Task<Integer> implements Callable<Integer> {
private Random random = new Random();
private List<Integer> list;
private Semaphore semaphore;
TestCallable(List<Integer> list, Semaphore semaphore) {
this.list = list;
this.semaphore = semaphore;
}
#Override
public Integer call(){
System.out.println("SENDING");
System.out.println(list);
try {
Thread.sleep(1000+random.nextInt(500));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("RECEIVED");
semaphore.release();
return list.size();
}
}
Task extends java.util.concurrent.FutureTask which in turn implements the Future interface. This means you can use a Task just like a Future.
Executor executor = ...;
Task<?> task = ...;
executor.execute(task);
task.get(); // Future method
This will cause the thread calling get() to wait until completion. However, a Task's purpose is to communicate the progress of a background process with the JavaFX Application Thread. It's close relationship to the GUI means you will most likely be launching a Task from the FX thread. This will lead to get() being called on the FX thread which is not what you want as it will freeze the GUI until get() returns; you might as well have just called Task.run directly.
Instead, you should be using the asynchronous functionality provided by Task. If you want to retrieve the value when the Task completes successfully you can use the onSucceeded property or listen to the value/state property. There's also ways to listen for failure/cancellation.
Executor executor = ...;
Task<?> task = ...;
task.setOnSucceeded(event -> handleResult(task.getValue()));
task.setOnFailed(event -> handleException(task.getException()));
executor.execute(task);
If you don't need the functionality provided by Task then it would probably be best to simply use Runnable or Callable directly.
It's not very clear what you want to do here.
Firstly, your Semaphore does nothing because you used Executors.newSingleThreadExecutor(), which already guarantees that only one task can run at any point in time.
Secondly, like what #Slaw mentioned, you are potentially blocking on JavaFX Application thread, depending on your actual implementation (your example isn't really a JavaFX application).
Next, ExecutorService has 2 main overloads for submit().
The first overload takes in a Callable. This overload allows you to retrieve the value returned by the Callable (by calling get() on the returned Future), because Callable refers to something that is can be called - it can return value.
The second overload takes in a Runnable. Since Task implements Future RunnableFuture interface, and Future RunnableFuture interface extends Runnable interface, passing in a Task would be equivalent to calling this overload. This overload does not expect a result to be returned, because Runnable is something that you run without a result. Calling get() on the Future returned by this overload will block until the task finishes, and null will be returned. If you need to retrieve the value returned by the Task, you need to call get() of the Task, not the Future returned by ExecutorService.submit().
Edit based on OP's comments
Firstly, since the calling method is already running in a background thread, and all tasks are expected to run sequentially (instead of parallelly), then you should just run them without all these additional ExecutorService and Task, unless there is another reason why this has to be done.
Secondly, a List object is nothing but an object doing referencing. What could have really affected performance is that you are copying the reference of the elements to the new list. You could have used List.subList()if the indices are known, as the returned list would use the same backing array as the original list, so there isn't an additional O(n) operation for copying.
My program searches for a solution (any solution) to a problem through a divide-and-conquer approach, implemented using recursion and RecursiveTasks's: I fork a task for the first branch of the division, then recurse into the second branch: if the second branch has found a solution, then I cancel the first branch, otherwise I wait for its result.
This is perhaps not optimal. One approach would be for any of the launched tasks to throw an exception if a solution is found. But then, how would I cancel all the launched tasks? Does cancelling a task also cancel all sub-tasks?
You can use the simple approach with task manager. For example:
public class TaskManager<T> {
private List<ForkJoinTask<T>> tasks;
public TaskManager() {
tasks = new ArrayList<>();
}
public void addTask(ForkJoinTask<T> task) {
tasks.add(task);
}
public void cancelAllExcludeTask(ForkJoinTask<Integer> cancelTask) {
for (ForkJoinTask<T> task : tasks) {
if (task != cancelTask) {
task.cancel(true);
}
}
}
public void cancelTask(ForkJoinTask<Integer> cancelTask) {
for (ForkJoinTask<T> task : tasks) {
if (task == cancelTask) {
task.cancel(true);
}
}
}
}
And the task:
public class YourTask extends RecursiveTask<Integer> {
private TaskManager<Integer> taskManager;
#Override
protected Integer compute() {
// stuff and fork
newTask.fork();
// do not forget to save in managers list
taskManager.addTask(newTask);
// another logic
// if current task should be cancelled
taskManager.cancelTasks(this);
// or if you have decided to cancel all other tasks
taskManager.cancelAllExcludeTask(this);
}
}
The framework cannot cancel a task for the same reason you cannot cancel a thread. See the documentation on Thread.stop() for all the reasons. What locks could the task be holding? What outside resources could it have linkage to? All the same Thread.stop() reasons apply to tasks as well (after all, tasks run under threads.) You need to tell the task to stop just like you tell a thread to stop.
I manage another fork/join project that uses the scatter-gather technique. The way I do a cancel, or short-circuit, is that every task I create is passed an object (PassObject) that has a
protected volatile boolean stop_now = false;
and a method for stopping the task
protected void stopNow() {stop_now = true; }
Each task periodically checks the stop_now and when true it gracefully ends the task.
Unfortunately, the stop_now needs to be volatile since another thread is going to set it. This can add significant overhead if you check it frequently.
How to set this field in another task gets a little tricky. Each task I create also contains a reference to the array of references to every other task
int nbr_tasks = nbr_elements / threshold;
// this holds the common class passed to each task
PassObject[] passList = new PassObject[nbr_tasks];
for (int i = 0; i < nbr_tasks; i++)
passList[i] = new PassObject( passList,… other parms);
Once the list is formed I fork() each object in passList. Each PassObject contains a reference to the array, passList, which contains a reference to every object that is passed to each task. Therefore, every task knows about every other task and when one task want to cancel the others it simply calls the cancelOthers method with a reference to the passList.
private void cancelOthers (PassObject[] others) {
// tell all tasks to stop
for (int i = 0, max = others.length; i < max; i++)
others[i].stopNow();
If you’re using Java8 then you can do a form of scatter-gather with the CountedCompler class instead of the RecusiveTask. For Java7 or if you still want to use RecursiveTask, then the first task in the recursion needs to create an AtomicBoolean field (AtomicBoolean stop_now = new AtomicBoolean(false);) and include a reference to this field in every new RecursiveTask it creates. With recursion, you don’t know how many levels of tasks you’ll need in the beginning.
Again, you’ll need to check for a true in the boolean periodically in your code and when true, end the task gracefully.
The above is just a hint of how you can do a cancel. Every application is different. What I do works for my application – but the logic is the same. You need something common in every task that a task can set and every other task can see.
I'd add more code but the code insert only is taking one line at a time and it isn't practical.
I have one "Runnable" threads which is initiating few "Callable" threads and I want to display results when all above threads has finished their jobs.
What is the best way to do it?
My code is as follows
Connector.java (Starting Runnable Thread)
public class Connector {
private static void anyFileConnector() {
// Starting searching Thread
ExecutorService executor = Executors.newFixedThreadPool(100);
executor.submit(traverse, executor);
//HERE I WANT MY ALL SEARCH RESULTS/OUTPUT : CURRENTLY IT IS STARTING OTHER THREADS AND NOT SHOWING ME ANY RESULTS BECAUSE NONE OF THEM WAS FINISHED.(IN CONSOLE, I WAS ABLE TO SEE RESULTS FROM ALL THE THREADS
setSearchResult(traverse.getResult());
executor.shutdown();
}
}
Traverse.java (Runnable Thread)
I am using ExecutorCompletionService to handle it...but it didn't create any difference.
:(
public class Traverse implements Runnable {
public void run() {
ExecutorService executor = Executors.newFixedThreadPool(100);
ExecutorCompletionService<List<ResultBean>> taskCompletionService =
new ExecutorCompletionService<List<ResultBean>>(executor);
try (DirectoryStream<Path> stream = Files
.newDirectoryStream(dir)) {
Search newSearch = new Search();
taskCompletionService.submit(newSearch);
}
list.addAll(taskCompletionService.take().get());
}
}
Search.java (Callable Thread)
public class Search implements Callable<List<ResultBean>> {
public List<ResultBean> call() {
synchronized (Search.class) {
// It will return results
return this.search();
}
}
}
Go for CyclicBarrier and you will be able to achieve this.
A cyclic barrier will perform a task as soon as all the threads are done with their work, this is where you can print the en result.
Check this lik for working of CyclicBarrier : http://javarevisited.blogspot.com/2012/07/cyclicbarrier-example-java-5-concurrency-tutorial.html
Easy - all the Callables will return Future objects which you can used to wait and get the result by calling Future.get() in a blocking wait way. So your problem is just a for loop waiting for each future on the callables blockingly.
After that, just aggregate the results to return to client.
The submit method of executor service can return a list of Future objects. What you can do for your case is call isDone() method of these Future objects in a while loop.
Whenever, any future task gets completed this method will return true. You can now call get() method on this to get the value returned by this task. In this way you could get hold of all the future task values without having to wait for any particular task to get complete (since your first future task could have the longest completion time)