Executing SwingWorker from SwingWorker - waits until first one stops - java

I'm trying to execute a SwingWorker (SubWorker) from another SwingWorker (MainWorker), and then I want the MainWorker to wait for the SubWorker to complete. In the mean time, the MainWorker should update itself according to property changes of the SubWorker.
public class MainWorker extends SwingWorker<Void,Void>
{
public Void doInBackground()
{
SubWorker sw = new SubWorker();
sw.execute();
try {
network.get(); // wait for completion
} catch (Exception ex) {
}
return null;
}
}
The problem is that the SubWorker's doInBackground method is not called until the MainWorker has finished, while the MainWorker is waiting for the SubWorker to finish.
How can I let the SubWorker run parallel to the MainWorker's activities?

If you have only one sub-worker, I'm not sure what is the point - why can't you just execute the task in the SW body?
If you have multiple parallel sub-tasks, and you want to group them and report on their progress, you don't really need separate SwingWorkers - just start threads or use an executor to schedule the tasks. If you want to publish interim results, pass a blocking queue to the tasks, where they would push the updates.
The main (or rather the only) SwingWorker would take items from that queue and update the GUI using the publish()/process() methods. When a subtask finishes work, it can push special token in the queue (or null). That's how you can keep track of the outstanding subtasks and decide when to terminate the loop.
Alternatively, if you have a bunch of self-contained tasks you can use CompletionService and update the status in similar way from the SW.

Related

Will Runnables block the UI thread?

I am trying to understand how UI thread's event queue works. I'm trying to run a code that can be broken into many parts but unfortunately it must run on the UI thread. So, in order to not block the UI thread and receive a ANR I was wondering if I can break that code in many Runnable objects and run them using runOnUiThread from another thread.
My question is, will this block the UI thread? If, for example, I have a piece of code that definitely runs in over 5 seconds and I break this code into, let's say 1000 Runnable objects, and add them to the event queue of the UI thread, will other events get processed by the UI thread between them?
Edit: I think I found a better way to express myself in case the above explanation is confusing.
The 1000 Runnable objects was just an example, in actual code I want to have at most 10.
Basically, I want 10 Runnable objects, each one initialising an Ad network on the UI thread. I want these Runnable objects to run one after another, not in parallel. Also, I want the UI thread to be able to process other events between running these objects, so that I don't get an ANR in case running all 10 run methods will take more than 5 seconds.
NOTE: I don't know why initialising Ad networks must be done on the UI thread, but it must, otherwise the app crashes. It also states in some of the networks' sdks' documentation that initialisation must happen on the UI thread. This is why I need to run them one after another on UI thread and I can't run them in parallel in the background.
Also, the app is actually a OpenGl game, so calls to running the Runnable objects will be made from a GL thread, not the main thread, so they will be added to the event queue, and not executed immediately.
Well, Runnable inside your runOnUiThread is just operation in Main Thread.
Imagine that some simple action like
textView.setText("example");
will block Main Thread for 5 ms. Usually you will not see it.
Now imagine that you have like 1000 same operations for 5 seconds. And every blocks Main Thread for 5 ms. Simple calculating 5ms * 1000 = 5000ms = 5 seconds. So it will block Main Thread permamently. But if you have 10 operations you will block only 50 ms, in other words its just 1% of load that you will not feel.
So possible amount of calls depends on size of View, how hard render is and how fast is device.
P.S. For adepts of AsyncTask - there is no real difference between runOnUiThread and AsyncTask because those 1000 Runnables will execute in Main Thread by the same way.
Even if I do same thing inside onCreate method of Activity that will block UI hard
Yes. Runnable executing on UI thread will block main thread.
Check if below approach is useful for you.
Create a Handler with Looper from Main :requestHandler
Create a Handler with Looper for main thread : responseHandler and override handleMessage method
post a Runnable task on requestHandler
Inside Runnable task, call sendMessage on responseHandler
This sendMessage result invocation of handleMessage in responseHandler.
Get attributes from the Message and process it, update UI
Sample code:
/* Handler */
Handler requestHandler = new Handler(Looper.getMainLooper());
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Adwork task is completed:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
for ( int i=0; i<10; i++) {
// Start Adwork task
Runnable myRunnable = new Runnable() {
#Override
public void run() {
try {
/* Your business logic goes here */
// Send some result after computation
String text = "" + (++rId);
Message msg = new Message();
msg.obj = text.toString();
responseHandler.sendMessage(msg);
System.out.println(text.toString());
} catch (Exception err) {
err.printStackTrace();
}
}
};
requestHandler.post(myRunnable);
}
Useful articles:
handlerthreads-and-why-you-should-be-using-them-in-your-android-apps
android-looper-handler-handlerthread-i
What you are looking for is an AsyncTask.
These are designed to do some background processing, while the UI thread continues. It will NOT block the UI and will NOT cause ANR.
Within the AsyncTask, is an onPostExecute method, which allows you to post results back to the UI. So it is not completely detached from the UI Thread. And an onProgressUpdate for connection during the background processing
Yes, you will feel animation will stop or start shutter if You run heavy operations in Ui thread. It's also depends of how fast device is.
What I would suggest you is to break your code in two parts. One that can be done in background and second that need Ui thread and execute them in AsyncTask.
Use doInBackgroud method to execute heavy operation and onPostExecute to update UI.
Note: If you break code into 1000 threads and run them in one moment, then probably You will hit device queue limit. (Break them into 10-50 parts. )

Queue print jobs in a separate single Thread for JavaFX

currently I am experimenting with Concurrency in Java/JavaFX. Printing must run in a different thread otherwise it will make the JavaFX main thread freeze for a couple seconds. Right now my printing is done with this simplified example.
public void print(PrintContent pt) {
setPrintContent(pt);
Thread thread = new Thread(this);
thread.start();
}
#Override
public void run() {
// send content to printer
}
With this code I am sending many print jobs parallel to my printer. Therefore I get the error telling me that my printer can only handle 1 print job at a time. Since I know that Threads cannot be reused, I would like to know if there is a possibility to queue up Threads, so that my printer only handles one print job at a time.
Thank you very much for your effort and your time.
Use a single threaded executor to execute the print jobs. It will create one (and only one) background thread and queue the jobs:
// it might be better not to make this static; but you need to ensure there is
// only one instance of this executor:
private static final Executor PRINT_QUEUE = Executors.newSingleThreadExecutor();
// ...
public void print(PrintContent pt) {
PRINT_QUEUE.execute(() -> {
// send content to printer
});
}
~~> WAY 1
You can implement your own BlockingQueue read this is very useful or use a default implementation from Java libraries tutorial
So after reading the above links,you add a method in your class like
public void addJob(Object job){
queue.put(job);
}
Secondly you implement a Thread that is running into an infinite while loop.Inside it you call the method
queue.take();
When the queue is empty this Thread is blocked waiting until a new Object is added,so you dont have to worry about spending cpu time.
Finally you can set some upper bounds so for example queue can contain .. 27 items.
Mention that in case of Thread failure you have to recreate it manually.
~~>WAY 2 Better Approach
You can use an Executors Interface:
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
From documentation:
Creates an Executor that uses a single worker thread operating off an
unbounded queue. (Note however that if this single thread terminates
due to a failure during execution prior to shutdown, a new one will
take its place if needed to execute subsequent tasks.) Tasks are
guaranteed to execute sequentially, and no more than one task will be
active at any given time.
With the method below you retrieve a result if the job has successfully done.
Future future = executorService.submit(new Callable(){ public Object call() throws Exception { System.out.println("Asynchronous Callable"); return "Callable Result"; } });
System.out.println("future.get() = " + future.get());
If future.get() returns null, the job has been done successfully.
Remember to call
executorService.shutdown(); because the active threads inside this ExecutorService may prevent the JVM from shutting down.
Full tutorial here

Increment sleep/wait time until required

I'm not very good in multi-threading, this might be a basic question. But i have'nt been able to find an answer.
Scenario:
Lets say I have an event listener which is fired by something. Every time the event is fired, i want to start a new thread which takes about 3 seconds to execute.
Problem:
The problem is that the event can be fired more than once in a second, and I don't want to start multiple threads at once.
Requirement:
How can I schedule a thread lets say at 1000ms after the event. If the event keeps on firing, i want to keep delaying the scheduled time of thread. This way my thread executes after 1000ms of the last time the event was fired.
The event listener, on start up, creates and starts a new private thread. The thread contain a list of tasks to do and executes them one at a time sequentially. Each time the even listener receives a new event, it creates a new task, and adds it to the list of tasks in the private thread.
EDIT: Eugene suggested using a Thread Pool, which might be beneficial in your case if you have a great amount of work to do with each task taking up considerable amount of time. Take a look at thread pools in Java API, like this: http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
I would use a ScheduledExecutorService - schedule the task to happen in one second and if there is a task already scheduled cancel it and schedule a new one to happen in one second
This way your task will execute one second after the last time the event was triggered.
private class Task implements Runnable {
#Override
public void run() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
private Future<?> scheduledTaskHandle;
private class Listener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (scheduledTaskHandle != null && !scheduledTaskHandle.isDone()) {
scheduledTaskHandle.cancel(false);
}
scheduledTaskHandle = executorService.schedule(new Task(), 1, TimeUnit.SECONDS);
}
}
The Task is a Runnable that does your long-running operation. the Listener is your listener class.
In the Listener.actionPerformed method we first check whether a task is already scheduled by using the Future, if it is we cancel it. We don't need to worry about race hazards here is if the tasks finishes in between the call to isDone and the call to cancel then nothing will happen.
If the task is running at the point when the Listener fires then that task will complete, as the cancel method is called with false. Another task will be scheduled to run one second after the firing of the listener or once the currently running task has completed (as we are only using a single thread no more than one task can run).
The Listener will then schedule a new execution of the task to happen in one second.

Java Wait for thread to finish

I have a thread downloading data and I want to wait until the download is finished before I load the data. Is there a standard way of doing this?
More Info:
I have a Download class that gets data from a URL (Serialized POJOs). Download is Runnable and Observable. It keeps track of the bytes downloaded and download size. I have a progress bar that displays the progress to the User. The GUI observes Download to update the progress bar.
When the POJO is downloaded I want to get it and move to the next step. Each step has to wait for the previous to finish. The problem is I cant think of a way to pause my application to wait for the download thread. Once the download is finished I want to call download.getObject() which will return the data as an object. I can then cast it and get on with the next download.
I have a helper class that manages the URLs for download and makes all of the calls to Download. This call will call getObject and do the casting. The Gui calls helper.getUser(). helper starts the thread running and I want it to 'know' when it is finished so it can return the casted object.
Any suggestions/examples? I am in the beginning stages of this design so I am willing to change it.
Update:
I followed http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html#get and used modal to block until the thread finished. The code was very messy and I don't like this approach. I will keep trying to find a 'clean' way to handle the workflow of the download processes.
Thread has a method that does that for you join which will block until the thread has finished executing.
You could use a CountDownLatch from the java.util.concurrent package. It is very useful when waiting for one or more threads to complete before continuing execution in the awaiting thread.
For example, waiting for three tasks to complete:
CountDownLatch latch = new CountDownLatch(3);
...
latch.await(); // Wait for countdown
The other thread(s) then each call latch.countDown() when complete with the their tasks. Once the countdown is complete, three in this example, the execution will continue.
Better alternatives to join() method have been evolved over a period of time.
ExecutorService.html#invokeAll is one alternative.
Executes the given tasks, returning a list of Futures holding their status and results when all complete. Future.isDone() is true for each element of the returned list.
Note that a completed task could have terminated either normally or by throwing an exception. The results of this method are undefined if the given collection is modified while this operation is in progress.
ForkJoinPool or Executors.html#newWorkStealingPool provides other alternatives to achieve the same purpose.
Example code snippet:
import java.util.concurrent.*;
import java.util.*;
public class InvokeAllDemo{
public InvokeAllDemo(){
System.out.println("creating service");
ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
List<MyCallable> futureList = new ArrayList<MyCallable>();
for ( int i=0; i<10; i++){
MyCallable myCallable = new MyCallable((long)i);
futureList.add(myCallable);
}
System.out.println("Start");
try{
List<Future<Long>> futures = service.invokeAll(futureList);
}catch(Exception err){
err.printStackTrace();
}
System.out.println("Completed");
service.shutdown();
}
public static void main(String args[]){
InvokeAllDemo demo = new InvokeAllDemo();
}
class MyCallable implements Callable<Long>{
Long id = 0L;
public MyCallable(Long val){
this.id = val;
}
public Long call(){
// Add your business logic
return id;
}
}
}
You can use join() to wait for all threads to finish. Like below:
for (int i = 0; i < 10; i++)
{
Thread T1 = new Thread(new ThreadTest(i));
T1.start();
try {
T1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
SwingWorker has doInBackground() which you can use to perform a task. You have the option to invoke get() and wait for the download to complete or you can override the done() method which will be invoked on the event dispatch thread once the SwingWorker completes.
The Swingworker has advantages to your current approach in that it has many of the features you are looking for so there is no need to reinvent the wheel. You are able to use the getProgress() and setProgress() methods as an alternative to an observer on the runnable for download progress. The done() method as I stated above is called after the worker finishes executing and is performed on the EDT, this allows you load the data after the download has completed.
I imagine that you're calling your download in a background thread such as provided by a SwingWorker. If so, then simply call your next code sequentially in the same SwingWorker's doInBackground method.
Generally, when you want to wait for a thread to finish, you should call join() on it.
Any suggestions/examples? I followed SwingWorker... The code was very messy and I don't like this approach.
Instead of get(), which waits for completion, use process() and setProgress() to show intermediate results, as suggested in this simple example or this related example.
The join() method allows one thread to wait for the completion of another.However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify.

How does one stop a thread without a stop() method?

I have question about the Java threads. Here is my scenario:
I have a thread calling a method that could take while. The thread keeps itself on that method until I get the result. If I send another request to that method in the same way, now there are two threads running (provided the first did not return the result yet). But I want to give the priority to the last thread and don't want to get the results from the previously started threads. So how could I get rid of earlier threads when I do not have a stop method?
The standard design pattern is to use a local variable in the thread that can be set to stop it:
public class MyThread extends Thread {
private volatile boolean running = true;
public void stop() {
running = false;
}
public void run() {
while (running) {
// do your things
}
}
}
This way you can greacefully terminate the thread, i.e. without throwing an InterruptedException.
The best way really depends on what that method does. If it waits on something, chances are an interrupt will result in an InterruptedException which you handle and cleanly exit. If it's doing something busy, it won't:
class Scratchpad {
public static void main(String[] a) {
Thread t = new Thread(new Runnable() {
public void run() {doWork();}
});
t.start();
try {
Thread.sleep(50);
} catch (InterruptedException ie) {}
t.interrupt();
}
private static void doWork() {
for ( long i = 1; i != 0; i *=5 );
}
}
In the case above, the only viable solution really is a flag variable to break out of the loop early on a cancel, ala #inflagranti.
Another option for event-driven architectures is the poison-pill: if your method is waiting on a blocking queue for a new item, then you can have a global constant item called the "poison-pill" that when consumed (dequeued) you kill the thread:
try {
while(true) {
SomeType next = queue.take();
if ( next == POISON_PILL ) {
return;
}
consume(next);
}
} catch //...
EDIT:
It looks like what you really want is an executor service. When you submit a job to an executor service, you get back a Future which you can use to track results and cancel the job.
You can interrupt a Thread, its execution chain will throw an InterruptedException most of the time (see special cases in the documentation).
If you just want to slow down the other thread and not have it exit, you can take some other approach...
For one thing, just like exiting you can have a de-prioritize variable that, when set, puts your thread to sleep for 100ms on each iteration. This would effectively stop it while your other thread searched, then when you re-prioritize it it would go back to full speed.
However, this is a little sloppy. Since you only ever want one thing running but you want to have it remember to process others when the priority one is done, you may want to place your processing into a class with a .process() method that is called repeatedly. When you wish to suspend processing of that request you simply stop calling .process on that object for a while.
In this way you can implement a stack of such objects and your thread would just execute stack.peek().process(); every iteration, so pushing a new, more important task onto the stack would automatically stop any previous task from operating.
This leads to much more flexible scheduling--for instance you could have process() return false if there is nothing for it to do at which point your scheduler might go to the next item on the stack and try its' process() method, giving you some serious multi-tasking ability in a single thread without overtaxing your resources (network, I'm guessing)
There is a setPriority(int) method for Thread. You can set the first thread its priority like this:
Thread t = new Thread(yourRunnable);
t.start();
t.setPriority(Thread.MIN_PRIORITY); // The range goes from 1 to 10, I think
But this won't kill your thread. If you have only two threads using your runnable, then this is a good solution. But if you create threads in a loop and you always sets the priority of the last thread to minimum, you will get a lot of threads.
If this is what is application is going to do, take a look at a ThreadPool. This isn't an existing class in the Java API. You will have create one by yourself.
A ThreadPool is another Thread that manages all your other Threads the way you want. You can set a maximum number of running Threads. And in that ThreadPool, you can implement a system that manages the Thread priority automatically. Eg: You can make that older threads gain more priority, so you can properly end them.
So, if you know how to work with a ThreadPool, it can be very interesting.
According to java.lang.Thread API, you should use interrupt() method and check for isInterrupted() flag while you're doing some time-consuming cancelable operation. This approach allows to deal with different kind of "waiting situations":
1. wait(), join() and sleep() methods will throw InterruptedExcetion after you invoke interrupt() method
2. If thread blocked by java.nio.channels.Selector it will finish selector operation
3. If you're waiting for I/O thread will receive ClosedByInterruptException, but in this case your I/O facility must implement InterruptibleChannel interface.
If it's not possible to interrupt this action in a generic way, you could simply abandon previous thread and get results from a new one. You could do it by means of java.util.concurrent.Future and java.util.concurrent.ExecutorService.
Cosider following code snippet:
public class RequestService<Result> {
private ExecutorService executor = Executors.newFixedThreadPool(3);
private Future<Result> result;
public Future<Result> doRequest(){
if(result !=null){
result.cancel(true);
}
result = executor.submit(new Callable<Result>() {
public Result call() throws Exception {
// do your long-running service call here
}
});
return result;
}
}
Future object here represents a results of service call. If you invoke doRequest method one more time, it attempts to cancel previous task and then try to submit new request. As far as thread pool contain more than one thread, you won't have to wait until previous request is cancelled. New request is submitted immediately and method returns you a new result of request.

Categories