I have a javafx app, and I want to surround some code with "waiting" feature. So my code can be Runnable and Callable. The problem is getting result from Callabe. I tried to play with:
wait()/notify()
Platform.runLater
creating daemon threads by hands
Service
after reading some articles here, but it doesn't help.
How I want to call it:
final String a =
CommonHelper.showWaiting(() -> {
System.out.println("test");
return "test2";
});
That's how I work with Runnable:
public static void showWaiting(Runnable runnable) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
try {
executorService.submit(new WaitingTask<>(executorService.submit(runnable)));
} finally {
executorService.shutdown();
}
}
And my WaitingTask is:
public class WaitingTask<T> extends Task<Void> {
#Getter
private final Future<T> future;
public WaitingTask(Future<T> future) {
this.future = future;
}
#Override
protected Void call() {
showSpinner();
while (true) {
if (future.isDone()) {
hideSpinner();
break;
}
}
}
return null;
}
}
That works awesome - my app shows waiting spinner, and task runns in separate thread.
So I try to work the same way with Callable to get the result:
public static <T> T showWaiting(Callable<T> callable) {
ExecutorService executorService = Executors.newFixedThreadPool(2);
try {
FutureTask<T> task = new FutureTask<>(callable);
Future<T> result = (Future<T>) executorService.submit(task);
executorService.submit(new WaitingTask<>(result));
return result.get();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
executorService.shutdown();
}
}
but I can not see waiting spinner, maybe the app's main thread waits for result.get(); and the app freezes. How can I fix it?
There are a few things you are doing incorrectly:
You wrap your Callable in a FutureTask before submitting it to an ExecutorService. You don't need to do this, and in fact you shouldn't do this. Instead, just submit your Callable directly and you will get a Future in return.
Future<T> future = executor.submit(callable);
If you're using the core implementation of ExecutorService the returned Future will be a FutureTask anyway. Not that you should care—the only important thing is that its a Future. Note the same goes for Runnables; just submit them directly, don't wrap them in a FutureTask first.
You're submitting your Callable, getting a Future, and wrapping said Future in a Task...and then submitting your Task. This means you will have two tasks for every one you want to execute. Depending on how your ExecutorService is configured, this equates to using two threads per task.
You should be using your Task as if it was your Callable. Do the work inside the Task#call() method and return the result. Then only submit the Task, don't wrap it in anything first.
executor.execute(task); // Don't need the Future here, just use "execute"
If you want the result of the Task you can register callbacks (see this). The class is designed to invoke these callbacks on the JavaFX Application Thread.
task.setOnSucceeded(event -> {
T value = task.getValue();
// do something with value...
});
Note that Task extends FutureTask. This seems contradictory to point 1, but that's just how it is. Personally, I wouldn't have designed the class that way—it ends up wrapping the Task in another Future (likely FutureTask) when executed using the Executor Framework.
This is related to number 2; if you fix that issue then this issue inherently goes away.
You are spin waiting for the wrapped Future to complete. This is a waste of resources. The Future interface has a get() method that will block the calling thread until said Future is done. If the Future completes normally you'll get the value in return, else if it completes exceptionally an ExecutionException will be thrown. The third option is the calling thread is interrupted and an InterruptedException is thrown.
If the method names "showSpinner" and "hideSpinner" aren't misleading, you are updating the UI from a background thread. Never update the UI from a thread other than the JavaFX Application Thread. Now, you could wrap those calls in a Platform.runLater action, but you could also use the properties/callbacks of the Task. For instance, you could listen to the running property to know when to show and hide your spinner.
Taking all that into account, your example should look more like:
// Doesn't have to be an anonymous class
Task<String> task = new Task<>() {
#Override
protected String call() {
System.out.println("test");
return "test2";
}
});
task.runningProperty().addListener((obs, wasRunning, isRunning) -> {
if (isRunning) {
showSpinner();
} else {
hideSpinner();
}
});
task.setOnSucceeded(event -> {
String a = task.getValue();
// Do something with value.
});
executorService.execute(task);
For more information, I suggest reading:
Concurrency in JavaFX
Documentation of javafx.concurrent.Worker
Documentation of javafx.concurrent.Task (and Worker's other implementations)
Possibly a tutorial on Java's Executor Framework.
Thanks all for help, especially #Slaw and #kendavidson
Finally I've found a simple and perfect solution here:
Modal JaxaFX Progress Indicator running in Background
Maybe I'll post my full generic-based example here, based on this principles
Related
I have a task that I want to run at a fixed rate. However I also need the result of the task after each execution. Here is what I tried:
The task
class ScheduledWork implements Callable<String>
{
public String call()
{
//do the task and return the result as a String
}
}
No I tried to use the ScheduledExecutorService to scheduled it. Turns out you cannot schedule a Callable at a fixed rate, only a Runnable can be done so.
Please advise.
Use a producer/consumer pattern: Have the Runnable put its result on a BlockingQueue. Have another thread take() from the queue.
Take is a blocking call (ie only returns when something is on the queue), so you'll get your results as soon as they're available.
You could combine this with the hollywood pattern to provide the waiting thread with a callback so your code gets called when something is available.
Unless if you don't care about the return value of your Callable, you can wrap it in a Runnable and use that to pass to ScheduledExecutorService.
public static Runnable runnableOf(final Callable<?> callable)
{
return new Runnable()
{
public void run()
{
try
{
callable.call();
}
catch (Exception e)
{
}
}
};
}
Then when you want to submit to ScheduledExecutroService you can pass your Callable:
ses.scheduleAtFixedRate(runnableOf(callabale), initialDelay, delay, unit);
when going through the ListenableFutre interface, it notes in the doc that
addListener()
Registers a listener to be run on the given executor. The listener
will run when the Future's computation is complete or, if the
computation is already complete, immediately.`
Since Future.get() is a blocking call, how does Java guarantee certain future is Done? are they spinning on this? I understand that with Framework like dagger producers, it is kinda easy to understand (once task is done, write to something, the monitoring thread will be notified). in ListenableFuture case, does jvm support something like this out of box?
using wait()/notify() like mechanism ?
FollowUp Question: as all of you put, it is the caller actually guarantee the listener to be run, normal case to use a ListenableFuture
would be ListenableFuture future = Caller.call(), with caller and callee in different threads or even in different JVMs, how is this done in java? the listener in stored in both the caller thread and callee thread ? or using remote reigstery when in differnt JVMs?
There's nothing magic going on with ListenableFuture - the contract of the interface simply requires that any implementations invoke any registered listeners upon completion (or immediately, if already done).
It may help to look at one such implementation, AbstractFuture - specifically look at the .complete() method, which is invoked immediately after the future becomes "done" (by finishing, failing, or being cancelled). In order to be both fast and thread-safe the details are somewhat complex, but essentially that's all it does.
As already mentioned, the best way to understand the ListenableFuture is to look how it is implemented. When you call addListener(Runnable listener, Executor exec), you provide a Runnable listener and an Executor to run this listener, so it is you who decides how your listener is executed.
the listener is stored in both the caller thread and callee thread ?
The listener is stored inside the future, in the ExecutionList:
// The execution list to hold our executors.
private final ExecutionList executionList = new ExecutionList();
And addListener(Runnable listener, Executor exec) does just following:
public void addListener(Runnable listener, Executor exec) {
executionList.add(listener, exec);
}
So when the future completes, it calls the set(V value) method:
protected boolean set(#Nullable V value) {
boolean result = sync.set(value);
if (result) {
executionList.execute();
}
return result;
}
and all listeners are executed like this: executor.execute(runnable);
I'd like to add answers.
Guava does not garantee it.
If you down JVM or JVM is crashed no listeners would be invoked.
If you shutdown executor without cancelling futures, no listeners would be invoked too. I mean this case:
ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(false);
return t;
}
});
ListenableFuture<?> listenableFuture = JdkFutureAdapters.listenInPoolThread(
executorService.submit(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("run!!!");
}
}),
executorService
);
Futures.addCallback(listenableFuture, new FutureCallback<Object>() {
#Override
public void onSuccess(#Nullable Object result) {
System.out.println("onSuccess");
}
#Override
public void onFailure(Throwable t) {
System.out.println("onFailure");
}
});
MoreExecutors.shutdownAndAwaitTermination(executorService, 3, TimeUnit.SECONDS);
I didn't see "onSuccess" or "onFailure", did you?
In usual workflow when JVM is running, Guava uses CAS to invoke listeners exactly once, you can see it in source code too.
What is the proper way to implement concurrency in Java applications? I know about Threads and stuff, of course, I have been programming for Java for 10 years now, but haven't had too much experience with concurrency.
For example, I have to asynchronously load a few resources, and only after all have been loaded, can I proceed and do more work. Needless to say, there is no order how they will finish. How do I do this?
In JavaScript, I like using the jQuery.deferred infrastructure, to say
$.when(deferred1,deferred2,deferred3...)
.done(
function(){//here everything is done
...
});
But what do I do in Java?
You can achieve it in multiple ways.
1.ExecutorService invokeAll() API
Executes the given tasks, returning a list of Futures holding their status and results when all complete.
2.CountDownLatch
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
A CountDownLatch is initialized with a given count. The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon -- the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.
3.ForkJoinPool or newWorkStealingPool() in Executors is other way
Have a look at related SE questions:
How to wait for a thread that spawns it's own thread?
Executors: How to synchronously wait until all tasks have finished if tasks are created recursively?
I would use parallel stream.
Stream.of(runnable1, runnable2, runnable3).parallel().forEach(r -> r.run());
// do something after all these are done.
If you need this to be asynchronous, then you might use a pool or Thread.
I have to asynchronously load a few resources,
You could collect these resources like this.
List<String> urls = ....
Map<String, String> map = urls.parallelStream()
.collect(Collectors.toMap(u -> u, u -> download(u)));
This will give you a mapping of all the resources once they have been downloaded concurrently. The concurrency will be the number of CPUs you have by default.
If I'm not using parallel Streams or Spring MVC's TaskExecutor, I usually use CountDownLatch. Instantiate with # of tasks, reduce once for each thread that completes its task. CountDownLatch.await() waits until the latch is at 0. Really useful.
Read more here: JavaDocs
Personally, I would do something like this if I am using Java 8 or later.
// Retrieving instagram followers
CompletableFuture<Integer> instagramFollowers = CompletableFuture.supplyAsync(() -> {
// getInstaFollowers(userId);
return 0; // default value
});
// Retrieving twitter followers
CompletableFuture<Integer> twitterFollowers = CompletableFuture.supplyAsync(() -> {
// getTwFollowers(userId);
return 0; // default value
});
System.out.println("Calculating Total Followers...");
CompletableFuture<Integer> totalFollowers = instagramFollowers
.thenCombine(twitterFollowers, (instaFollowers, twFollowers) -> {
return instaFollowers + twFollowers; // can be replaced with method reference
});
System.out.println("Total followers: " + totalFollowers.get()); // blocks until both the above tasks are complete
I used supplyAsync() as I am returning some value (no. of followers in this case) from the tasks otherwise I could have used runAsync(). Both of these run the task in a separate thread.
Finally, I used thenCombine() to join both the CompletableFuture. You could also use thenCompose() to join two CompletableFuture if one depends on the other. But in this case, as both the tasks can be executed in parallel, I used thenCombine().
The methods getInstaFollowers(userId) and getTwFollowers(userId) are simple HTTP calls or something.
You can use a ThreadPool and Executors to do this.
https://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
This is an example I use Threads. Its a static executerService with a fixed size of 50 threads.
public class ThreadPoolExecutor {
private static final ExecutorService executorService = Executors.newFixedThreadPool(50,
new ThreadFactoryBuilder().setNameFormat("thread-%d").build());
private static ThreadPoolExecutor instance = new ThreadPoolExecutor();
public static ThreadPoolExecutor getInstance() {
return instance;
}
public <T> Future<? extends T> queueJob(Callable<? extends T> task) {
return executorService.submit(task);
}
public void shutdown() {
executorService.shutdown();
}
}
The business logic for the executer is used like this: (You can use Callable or Runnable. Callable can return something, Runnable not)
public class MultipleExecutor implements Callable<ReturnType> {//your code}
And the call of the executer:
ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutor.getInstance();
List<Future<? extends ReturnType>> results = new LinkedList<>();
for (Type Type : typeList) {
Future<? extends ReturnType> future = threadPoolExecutor.queueJob(
new MultipleExecutor(needed parameters));
results.add(future);
}
for (Future<? extends ReturnType> result : results) {
try {
if (result.get() != null) {
result.get(); // here you get the return of one thread
}
} catch (InterruptedException | ExecutionException e) {
logger.error(e, e);
}
}
The same behaviour as with $.Deferred in jQuery you can archive in Java 8 with a class called CompletableFuture. This class provides the API for working with Promises. In order to create async code you can use one of it's static creational methods like #runAsync, #supplyAsync. Then applying some computation of results with #thenApply.
I usually opt for an async notify-start, notify-progress, notify-end approach:
class Task extends Thread {
private ThreadLauncher parent;
public Task(ThreadLauncher parent) {
super();
this.parent = parent;
}
public void run() {
doStuff();
parent.notifyEnd(this);
}
public /*abstract*/ void doStuff() {
// ...
}
}
class ThreadLauncher {
public void stuff() {
for (int i=0; i<10; i++)
new Task(this).start();
}
public void notifyEnd(Task who) {
// ...
}
}
I have several async methods (Annotatad #Asynchronous) Returning Future Objects. I have to execute them at once but it would be enough for me to get the result of the first one which ready, is there any nice and safe solutions for that that works on a Java EE container?
Thanks!
There's no standard API for this facility. Just check Future#isDone() yourself in an infinite loop on the current thread in an utility method which look like below:
public static <T> Future<T> getFirstDone(List<Future<T>> futures) {
while (true) {
for (Future<T> future : futures) {
if (future.isDone()) {
return future;
}
}
// Break if necessary infinite loop here once it reaches certain timeout.
}
}
Usage:
List<Future<Foo>> results = collectThemSomehow();
Future<Foo> firstDoneResult = getFirstDone(results);
// ...
Here is an example of how it can works with Spring. In this example, the asynchronous job simply returns a boolean.
public void example(Job job) throws Exception
{
Future<Boolean> executor = jobExecutor.doJob(job);
//wait to be done
while (!executor.isDone()) {
Thread.sleep(10);
}
System.out.println(executor.get());
}
The job executor class is annoted #Component.
#Async
public Future<Boolean> doJob(Job job) throws Exception {
boolean isSuccessful;
//do something
return new AsyncResult<Boolean>(isSuccessful);
}
Sometimes you can invert it - transfer function pointer to async method and call it:
AtomicBoolean executed = new AtomicBoolean(false);
Runnable r = () ->{
if(!executed.getAndSet(true)){
//do job
}
};
But be careful: this code is executed inside worker thread, not original thread.
I have a situation that I need to work on
I have a class which has send method, example
#Singleton
class SendReport {
public void send() {}
}
The send method is called from a user click on web page, and must return immediately, but must start a sequence of tasks that will take time
send
->|
| |-> Task1
<-| |
<-|
|
|-> Task2 (can only start when Task1 completes/throws exception)
<-|
|
|-> Task3 (can only start when Task2 completes/throws exception)
<-|
I am new to Java concurrent world and was reading about it. As per my understanding, I need a Executor Service and submit() a job(Task1) to process and get the Future back to continue.
Am I correct?
The difficult part for me to understand and design is
- How and where to handle exceptions by any such task?
- As far as I see, do I have to do something like?
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future futureTask1 = executorService.submit(new Callable(){
public Object call() throws Exception {
System.out.println("doing Task1");
return "Task1 Result";
}
});
if (futureTask1.get() != null) {
Future futureTask2 = executorService.submit(new Callable(){
public Object call() throws Exception {
System.out.println("doing Task2");
return "Task2 Result";
}
}
... and so on for Task 3
Is it correct?
if yes, is there a better recommended way?
Thanks
Dependent task execution is made easy with Dexecutor
Disclaimer : I am the owner
Here is an example, it can run the following complex graph very easily, you can refer this for more details
Here is an example
If you just have a line of tasks that need to be called on completion of the previous one than as stated and discussed in the previous answers I don't think you need multiple threads at all.
If you have a pool of tasks and some of them needs to know the outcome of another task while others don't care you can then come up with a dependent callable implementation.
public class DependentCallable implements Callable {
private final String name;
private final Future pre;
public DependentCallable(String name, Future pre) {
this.name = name;
this.pre = pre;
}
#Override
public Object call() throws Exception {
if (pre != null) {
pre.get();
//pre.get(10, TimeUnit.SECONDS);
}
System.out.println(name);
return name;
}
A few other things you need to take care of based on the code in your question, get rid of future.gets in between submits as stated in previous replies. Use a thread pool size of which is at least greater than the depth of dependencies between callables.
Your current approach will not work as it will block till the total completion which you wanted to avoid.
future.get() is blocking();
so after submitting first Task, your code will wait till its finished and then next task will be submitted, again wait, so there is no advantage over single thread executing the tasks one by one.
so if anything the code would need to be:
Future futureTask2 = executorService.submit(new Callable(){
public Object call() throws Exception {
futureTask1.get()
System.out.println("doing Task2");
return "Task2 Result";
}
}
your graph suggests that the subsequent task should execute despite exceptions. The ExecutionException will be thrown from get if there was problem with computation so you need to guard the get() with appropriate try.
Since Task1, Task2 have to completed one after another, why you do you want them exececuted in different threads. Why not have one thread with run method that deals with Task1,Task2.. one by one. As you said not your "main" thread, it can be in the executor job but one that handles all the tasks.
I personally don't like anonymous inner classes and callback (that is what you kind of mimic with chain of futures). If I would have to implement sequence of tasks I would actually implement queue of tasks and processors that executes them.
Mainly cause it is "more manageable", as I could monitor the content of the queue or even remove not necessary tasks.
So I would have a BlockingQueue<JobDescription> into which I would submit the JobDescription containing all the data necessary for the Task execution.
I would implement threads (Processors) that in their run() will have infinitive loop in which they take the job from the queue, do the task, and put back into the queue the following task. Something in those lines.
But if the Tasks are predefined at the send method, I would simply have them submitted as one job and then execute in one thread. If they are always sequential then there is no point in splitting them between different threads.
You need to add one more task if you want to return send request immediately. Please check the following example. It submits the request to the background thread which will execute the tasks sequentially and then returns.
Callable Objects for 3 long running tasks.
public class Task1 implements Callable<String> {
public String call() throws Exception {
Thread.sleep(5000);
System.out.println("Executing Task1...");
return Thread.currentThread().getName();
}
}
public class Task2 implements Callable<String> {
public String call() throws Exception {
Thread.sleep(5000);
System.out.println("Executing Task2...");
return Thread.currentThread().getName();
}
}
public class Task3 implements Callable<String> {
public String call() throws Exception {
Thread.sleep(5000);
System.out.println("Executing Task3...");
return Thread.currentThread().getName();
}
}
Main method that gets request from the client and returns immediately, and then starts executing tasks sequentially.
public class ThreadTest {
public static void main(String[] args) {
final ExecutorService executorService = Executors.newFixedThreadPool(5);
executorService.submit(new Runnable() {
public void run() {
try {
Future<String> result1 = executorService.submit(new Task1());
if (result1.get() != null) {
Future<String> result2 = executorService.submit(new Task2());
if (result2.get() != null) {
executorService.submit(new Task3());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
});
System.out.println("Submitted request...");
}
}