I am creating an MVP application with Java Swing. I need to execute various Tasks that are instances of a Taskclass, I created extending SwingWorker class!
I came across Executors class but none of the provided executors seem to fulfil my needs.
I want to execute some of my Task instances concurrently and some of my Task instances in queue. Also, I want a method invocation when all tasks have been completed. Like, done method in SwingWorker class!
abstract class CustomExecutor extends ThreadPoolExecutor {
CustomExecutor(Collection<Task> synchronousTasks, Collection<Task> asynchronousTasks) {
// .........
}
// To be called when all tasks have been executed successfully!
abstract void done();
}
I have not used ExecutorService or ThreadPoolExecutor before and unable to come up with any solution!
Let's briefly compare the two solutions you mentioned - SwingWorker and Executors framework. The general idea behind the two solutions is similar, but depending on the use case one can be better over the other.
SwingWorker
executes asynchronously the logic implemented in the doInBackground method.
you need to subclass SwingWorker to implement the logic
there are some useful methods to integrate with Swing and update the UI in the Event Dispatch Thread - publish(), process(), done(), get/setProgress() and some property change listener support methods.
a single instance of SwingWorker corresponds to a single task
when you invoke SwingWorker.execute(), internally the worker instance submits itself as a task (Callable) to an ExecutorService (to be precise - a ThreadPoolExecutor) so that the logic implemented in the doInBackground method is executed asynchronously in a separate thread
there is a default configuration of the ThreadPoolExecutor used by all the SwingWorker objects you ever create, hidden in the SwingWorker class. If you want to provide your own ExecutorService for executing the SwingWorkers, you can do so by setting sun.awt.AppContext.getAppContext().put(SwingWorker.class, yourOwnExecutorService). However, as I said, you can have only one global ExecutorService for all the SwingWorkers in your application.
to summarize: SwingWorker hides the concurrency details from you, but exposes API to communicate with the Swing UI. Use SwingWorker if your tasks first need to do some computation in the background and then update the UI.
More about Concurrency in Swing
Executors framework
You are in full control of the ExecutorService configuration - there are utility methods in the Executors class to create some common configurations or you can instantiate a ThreadPoolExecutor yourself.
The framework is generic - it accepts any Runnable/Callable tasks, which may perform any logic. There is no special support for Swing.
You need to shutdown the ExecutorService yourself.
More about Executors Framework
If I understand your requirement correctly, you might prefer to use ExecutorService rather than SwingWorker, so that you have more control over the concurrency. Submit the tasks that you want to be queued (ie. executed sequentially) to an executor created with Executors#newSingleThreadExecutor(). For the tasks that you want to be executed concurrently, use a different ExecutorService - created with Executors#newCachedThreadPool(), Executors#newFixedThreadPool(int) or a custom ThreadPoolExecutor. See Javadocs to check which fits your needs best.
You can use ExecutorService#invokeAll() to submit multiple tasks at once and to block until they are done or you can call ExecutorService#submit() in a loop to submit them one by one without blocking and at a later moment call Future.get() on the Future obtained from submit() to block until the execution is done.
Once you have called get() on all futures - both those corresponding to synchronousTasks and asynchronousTasks, you know that all are done and you can call your done() method.
If you want to learn even more, I recommend reading the Javadocs and the source code of SwingWorker, Executor and ExecutorService classes.
Related
Im using Java Executor framework to execute multiple threads at a same time. I would like to do some operations after all the threads are executed. Do we have any listeners or event capture mechanism in executor framework
The API docks for ThreadPoolExecutor describe some hooks that might be useful for this:
Hook methods
This class provides protected overridable beforeExecute(java.lang.Thread, java.lang.Runnable) and
afterExecute(java.lang.Runnable, java.lang.Throwable) methods that are
called before and after execution of each task. These can be used to
manipulate the execution environment; for example, reinitializing
ThreadLocals, gathering statistics, or adding log entries.
Additionally, method terminated() can be overridden to perform any
special processing that needs to be done once the Executor has fully
terminated.
If hook or callback methods throw exceptions, internal worker threads may in turn fail and abruptly terminate.
See https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html
You might consider moving from a ThreadPoolExecutor to a ScheduledThreadPoolExecutor. The difference is, that for all the tasks you enqueue, you'll get a Future<T>.
This allows you to check for .isDone() of tasks you submitted and act accordingly. Especially interesting if you need to use results of what you submitted, because you can cleanly perform a .get() then, without blocking the calling thread until the execution is finished.
Another alternative might be to implement a ThreadFactory, which spawns an additional listener thread to join() the main thread and notify you upon completion.
A a = new A();
B b= new B();
FutureTask fa = new FutureTask (a);
FutureTask fb = new FutureTask (b);
ExecutorService es = Executors.newFixedThreadPool(2);
es.submit (fa);
es.submit(fb);
String getName = (String)a.get();
String getSurName = (String)b.get();
es.shutdown ();
***//Here all threads are executed and
//you can write any code which you want to execute after
//finishing all the threads.***
Or the other work around .
....
you can write daemon class by using LocalThrad class and spawn the thread and it will act as listener for you.
Whatever you want to achieve in this case you can achieve by using above daemon class.
Timer creates its own thread and ScheduledThreadPoolExecutor uses a pool. Is their a way to specify the thread where the task will be executed directly without having to marshal any code? And if this is a bad idea, please explain why (beside the thread being busy).
I have no problem with the looper-handler approach, I'm just curious.
You can create a ScheduledThreadPoolExecutor with one single thread using Executors.newSingleThreadScheduledExecutor().
Optionally, you can pass a ThreadFactory as parameter if you want to have more control about this single thread. The thread factory's newThread(Runnable) method is called every time the executor wants to have a new Thread instance that should run the given Runnable (which is not identical to the Runnable you pass to the executor's execute(...), submit(...) or schedule(...) methods).
Note that you are not able to reuse an existing thread, as there is no way to 'inject' code into an already running thread in general, as it is possible in Qt. There, every thread has its own event queue and timing facility, so you can freely decide which (already existing) thread should process your timed task (see Timers in Qt).
There is no such feature in Java out of the box.
Is there an ExecutorService that allows an existing thread to perform the executions instead of spawning new threads? Bonus if it’s a ScheduledExecutor. Most executors spawn worker threads to do the execution, but I want the worker thread to be an existing thread that I’m on. Here's the API that I imagine:
while (!executor.isTerminated()) {
Runnable r = executor.take();
r.run();
}
This is similar to the way that SWT and JavaFX allow the main thread to dispatch events, as opposed to Swing, which requires its own event dispatch thread to be spawned to handle events.
Motivation: I currently have lots of places where a thread spawn a new executor and then just calls awaitTermination() to wait for it to finish. I’d like to save some resources and keep the stack traces from being split in two.
Note that I don’t want an executor that runs tasks in execute(Runnable)’s caller threads, which is what this answer and Guava’s MoreExecutors.sameThreadExecutor() do.
Most executors from java.util.concurrent behave exactly as you supposed. Some spawn additional threads when there are too many tasks, but usually they can be configured to set a limit.
To exploit such a behaviour, do not start new executor each time - use the same executor. To wait for a set of tasks to finish, use invokeAll(), or submit() and then future.get()
I'm assuming what you want is control over the creation of new threads, such as name, daemon-status, etc. Use a ThreadFactory:
public class MyThreadFactory implements ThreadFactory {
public Thread newThread(Runnable runnable) {
Thread t = new Thread(runnable, "MyThreadName");
t.setDaemon(true);
return t;
}
}
This allows you to control thread creation so that the execution happens in threads that you manufacture instead of some default thread from a default ThreadFactory.
Then to use it, all of the methods in Executors take a ThreadFactory:
Executors.newExecutorOfSomeKind(new MyThreadFactory());
Edit: I see what you mean now. Unfortunately, the behavior of all Executor implementations (as far as I'm aware) is to create new threads to run the task, except the sameThreadExecutor you mentioned. Without going through the Thread objects that are creating executors just to execute one task (which is a horrible design -- see comments for what I mean by this), there's no easy way to accomplish what you want. I would recommend changing the code to use a single Executor with something like an ExecutorCompletionService (see this question) or use a fork/join pattern. Fork/join is made easier in Java 7 (see this Java trail). For pre-Java 7 code, read up on the counting Semaphore in Java (and in general).
In Java is there a way to set the priority for the thread that will be calling the doInBackground() method of a SwingWorker object?
In the Thread API there is a setPriority() method. The SwingWorker.execute() method schedules the swingworker for execution on a worker thread. I would like to have access to that worker thread to set it's priority.
From my understanding this worker thread comes from a default worker thread pool. Would the only way to handle this is to use my own executor?
The JDK7 SwingWorker javadoc hints that the designers did not intend for users to directly interact with or alter the background threads:
... the exact strategy of choosing a thread for any particular SwingWorker is unspecified and should not be relied on.
The implementation of SwingWorker.getWorkersExecutorService() seems to reinforce this idea as they've implemented it in a way that is not easily changed.
SwingWorker is a boilerplate solution to the typical case and you don't have a typical case. I'd suggest you write the code to handle running the background tasks instead of trying to hack SwingWorker to do what you want. That way whoever gets to maintain your code in the future (perhaps even yourself!) won't be left wondering why SwingWorker isn't behaving as expected.
The only way I can think to do this is to have the execute method grab the current thread using Thread.currentThread(). You can then set the priority of this thread (provided the caller is allowed to).
As the SwingWorker is a Runnable, you can submit it to any java.util.concurrent.ExecutorService
I have a program that builds the GUI in the constructor. I need a Thread separate from the EDT to run immediately after the object in question is constructed. Could anyone point me in the right direction?
I need a Thread separate from the EDT
Threads are separate from the EDT so all you do is create a Runnable and then start it.
You only have to worry if the Thread updates any GUI components. If this is the case then you may want to use a SwingWorker. Read the section from the Swing tutorial on Concurrency for more information.
What you want to use is a SwingWorker<T,V>. In the doInBackground method, open the connection and start fetching data. When you have enough data to update the gui, call the publish method. Implement the process method to update the gui with the new data from publish, and finally, implement the done method to notify the user when you're finished fetching data.
The Swing Worker is a generic, so when you construct it you need to provide two types: T and V. V is the type for the data passed between publish and process methods and T is the type returned by doInBackground and passed to done.
build your GUI an open a new window inside a new Runnable invoked called by: SwingUtilities.invokeLater
you have two choises
1) wrap Thread into Runnable as demonstrated here
2) I am not very satisfy with plain SwingExecutor, then I use for that Executor and SwingWorker, monitored by PropertyChangeListener, example here,
please carrefully with number of threads started by Executor. Executor doesn't care if SwingWorker ends or not and there still exists Bug where is pretty possible to overload maximum (somewhere in API) simultaneous jobs live by Executor in same time.
by this reason is there possible implements PropertyChangeListener