Waiting for result using synchronized block causes App freeze - java

I have an object Task (see com.google.android.gms.tasks)
I need to wait till It has finished all operations before return result.
So I have tried to create a dummy object
final static Object lock=new Object();
to use as lock and I have added in the method
synchronized(lock){
lock.wait();
}
so that It doesn't return the value before task completion
calling lock.notifyAll in onSuccess() listener of the task (this listener is called when the task ends correctly).
But unfortunately the whole App freeze.
Why happens this?
How should I deal with Task completion?
(Note that Task isn't like AsyncTask)

There is a simple way to run a Task synchronously.
Tasks.await(yourTask);
But make sure this is called in a background thread.

Related

Main thread: can runnables be preempted?

I've a runnable instance that self-schedules itself again at the end of its run method:
private class MyRunnable implements Runnable {
private volatile boolean cancelled = false;
private Handler handler;
public MyRunnable(Handler h){
handler = h;
}
#Override
public void run(){
//Do stuff
if(!cancelled){
//Preemtion possible here?
handler.postDelayed(this, 1000);
}
}
public void selfStart(){
cancelled = false;
handler.removeCallbacks(this);
handler.post(this);
}
public void selfCancel(){
cancelled = true;
handler.removeCallbacks(this);
}
}
The runnable is first scheduled in the main thread calling selfStart from an activity's onStart.
At the same time, the runnable can be externally cancelled (calling selfCancel) from the activity's onStop and also from a Broadcast Receiver.
AFAIK Runnable.run, Activity.onStop and BroadcastReceiver.onReceive run in the same thread (the main one), so at first glance I thought there would be no thread-safety issues.
But it looks like sometimes, the runnable is being preemted in the middle of its run call, then it is cancelled from the activity or receiver, and then it resumes and re-schedules itself again.
Is this possible?
UPDATE:
I'll try to explain better the issue. The class shown above is intended to run tasks periodically in the main thread. In the "do stuff" comment there's actually code that updates a TextView with a value passed to the MyRunnable constructor. The activity cancels the current runnable and starts a new one when certain intents are received. Despite the current runnable is always requested to cancel itself before the new one is created, sometimes it is being left running along with the new one, so the text view is showing alternating values. This is not the intended behavior.
I thought if the runnable was currently running in the main thread, it would run until completion, and then other runnables or event handlers would be taken out of the queue and executed if needed, but no pending event or runnable could be "half executed".
There are two kinds of tasks running in the main thread that are related to the problem:
R1: The MyRunnable self-scheduling task. Runs and then it self-posts itself again with a delay of 1s.
R2: The event handlers that request cancellation of the current MyRunnable instance and create a new R1'. These happen randomly and are executed only once.
I've contemplated two scenarios. The first one:
R1 is already running in the main thread.
R2 arrives and is enqueued in the main thread.
R1 finishes running and posts itself again.
R2 runs and removes callbacks for R1.
R1 should never run again.
And the second one:
R1 is not running but is scheduled.
R2 arrives and removes callbacks for R1.
R1 should never run again.
Theoretically, if there's no preemtion, and there's only a single thread, how comes sometimes there are two R1s in the main thread?
As you have no synchronization on selfStart or selfCancel this is entirely possible.
An unreleated note, selfCancel could be called on a separate thread after your if statement in your run method has checked the value of cancelled. MyRunnable would then get one more call to run, which would end immediately as it's been cancelled.
My suggestion would be to move the //Do stuff inside the canceled check.
This avoids the race regardless of assumptions about which thread things are running on.
#Override
public void run(){
if(!cancelled){
//Do stuff
handler.post(this);
}
}
In general for maintainability, try to write code that works correctly regardless of the thread it is being run on. You never know when somebody will call selfCancel() on some other thread later thinking it is okay, when you have assumed they won't do that.
Well as others have said, there's no way a runnable can be preempted in a single thread. I also thought this idea was absurd. Shame on me for coming up with that nonsense.
There was nothing wrong with the runnables themselves. They were launched in the activity's onStart, and cancelled from Intents received by the activity, or in the activity's onStop. An this is the root of the problem: assuming onStart and onStop would run in a predictable order. Sometimes when coming back to the activity, a second onStart was executed before the first activity's onStop. Two tasks were running and the thing messed up to a point where the first task was never terminated.
Ensuring no task is launched without previous termination of the current one solved the issue.

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.

Executing SwingWorker from SwingWorker - waits until first one stops

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.

How do I have 1 UI thread wait for another UI thread

I have two UI threads.
I want to make sure the first one is finishing running, and then run the other one.
How could I do that?
Thanks a lot!
UIJob uiJob = new UIJob("settext1") {
public IStatus runInUIThread(IProgressMonitor ipm) {
webBrowser.setText(finalContent);
return Status.OK_STATUS;
}
};
uiJob.schedule();
UIJob uiJob2 = new UIJob("settext2") {
public IStatus runInUIThread(IProgressMonitor ipm) {
webBrowser.execute(executeMoreFunction);
return Status.OK_STATUS;
}
};
uiJob2.schedule();
From eclipse sdk help:
The UIJob is a Job that runs within the UI Thread via an asyncExec.
It is only one UI thread, two UIJob:s cannot wait for eachother, it will create a deadlock.
Call the join method after schedule.
Waits until this job is finished. This method will block the calling thread until the
job has finished executing, or until this thread has been interrupted. If the job
has not been scheduled, this method returns immediately. A job must not
be joined from within the scope of its run method.
If this method is called on a job that reschedules itself from within the
run method, the join will return at the end of the first execution.
In other words, join will return the first time this job exits the
RUNNING state, or as soon as this job enters the NONE state.
If this method is called while the job manager is suspended, this job
will only be joined if it is already running; if this job is waiting or sleeping,
this method returns immediately.
Note that there is a deadlock risk when using join. If the calling thread owns
a lock or object monitor that the joined thread is waiting for, deadlock
will occur.
Read more: http://kickjava.com/src/org/eclipse/core/runtime/jobs/Job.java.htm#ixzz0qWh6Ahhe

How to start/stop/restart a thread in Java?

I am having a real hard time finding a way to start, stop, and restart a thread in Java.
Specifically, I have a class Task (currently implements Runnable) in a file Task.java. My main application needs to be able to START this task on a thread, STOP (kill) the thread when it needs to, and sometimes KILL & RESTART the thread...
My first attempt was with ExecutorService but I can't seem to find a way for it restart a task. When I use .shutdownnow() any future call to .execute() fails because the ExecutorService is "shutdown"...
So, how could I accomplish this?
Once a thread stops you cannot restart it. However, there is nothing stopping you from creating and starting a new thread.
Option 1: Create a new thread rather than trying to restart.
Option 2: Instead of letting the thread stop, have it wait and then when it receives notification you can allow it to do work again. This way the thread never stops and will never need to be restarted.
Edit based on comment:
To "kill" the thread you can do something like the following.
yourThread.setIsTerminating(true); // tell the thread to stop
yourThread.join(); // wait for the thread to stop
Review java.lang.Thread.
To start or restart (once a thread is stopped, you can't restart that same thread, but it doesn't matter; just create a new Thread instance):
// Create your Runnable instance
Task task = new Task(...);
// Start a thread and run your Runnable
Thread t = new Thread(task);
To stop it, have a method on your Task instance that sets a flag to tell the run method to exit; returning from run exits the thread. If your calling code needs to know the thread really has stopped before it returns, you can use join:
// Tell Task to stop
task.setStopFlag(true);
// Wait for it to do so
t.join();
Regarding restarting: Even though a Thread can't be restarted, you can reuse your Runnable instance with a new thread if it has state and such you want to keep; that comes to the same thing. Just make sure your Runnable is designed to allow multiple calls to run.
It is impossible to terminate a thread unless the code running in that thread checks for and allows termination.
You said: "Sadly I must kill/restart it ... I don't have complete control over the contents of the thread and for my situation it requires a restart"
If the contents of the thread does not allow for termination of its exectuion then you can not terminate that thread.
In your post you said: "My first attempt was with ExecutorService but I can't seem to find a way for it restart a task. When I use .shutdownnow()..."
If you look at the source of "shutdownnow" it just runs through and interrupts the currently running threads. This will not stop their execution unless the code in those threads checks to see if it has been ineterrupted and, if so, stops execution itself. So shutdownnow is probably not doing what you think.
Let me illustrate what I mean when I say that the contents of the thread must allow for that thread to be terminated:
myExecutor.execute(new Runnable() {
public void run() {
while (true) {
System.out.println("running");
}
}
});
myExecutor.shutdownnow();
That thread will continue to run forever, even though shutdownnow was called, because it never checks to see if it has been terminated or not. This thread, however, will shut down:
myExecutor.execute(new Runnable() {
public void run() {
while (!Thread.interrupted()) {
System.out.println("running");
}
}
});
myExecutor.shutdownnow();
Since this thread checks to see whether or not it has been interrupted / shut down / terminated.
So if you want a thread that you can shut down, you need to make sure it checks to see if it has been interrupted. If you want a thread that you can "shut down" and "restart" you can make a runnable that can take new tasks as was mentioned before.
Why can you not shut down a running thread? Well I actually lied, you can call "yourThread.stop()" but why is this a bad idea? The thread could be in a synchronized (or other critical section, but we will limit ourselves to setions guarded by the syncrhonized key word here) section of code when you stop it. synch blocks are supposed to be executed in their entirity and only by one thread before being accessed by some other thread. If you stop a thread in the middle of a synch block, the protection put into place by the synch block is invalidated and your program will get into an unknown state. Developers make put stuff in synch blocks to keep things in synch, if you use threadInstance.stop() you destroy the meaning of synchronize, what the developer of that code was trying to accomplish and how the developer of that code expected his synchronized blocks to behave.
You can't restart a thread so your best option is to save the current state of the object at the time the thread was stopped and when operations need to continue on that object you can recreate that object using the saved and then start the new thread.
These two articles Swing Worker and Concurrency may help you determine the best solution for your problem.
As stated by Taylor L, you can't just "stop" a thread (by calling a simple method) due to the fact that it could leave your system in an unstable state as the external calling thread may not know what is going on inside your thread.
With this said, the best way to "stop" a thread is to have the thread keep an eye on itself and to have it know and understand when it should stop.
If your task is performing some kind of action in a loop there is a way to pause/restart processing, but I think it would have to be outside what the Thread API currently offers. If its a single shot process I am not aware of any way to suspend/restart without running into API that has been deprecated or is no longer allowed.
As for looped processes, the easiest way I could think of is that the code that spawns the Task instantiates a ReentrantLock and passes it to the task, as well as keeping a reference itself. Every time the Task enters its loop it attempts a lock on the ReentrantLock instance and when the loop completes it should unlock. You may want to encapsulate all this try/finally, making sure you let go of the lock at the end of the loop, even if an exception is thrown.
If you want to pause the task simply attempt a lock from the main code (since you kept a reference handy). What this will do is wait for the loop to complete and not let it start another iteration (since the main thread is holding a lock). To restart the thread simply unlock from the main code, this will allow the task to resume its loops.
To permanently stop the thread I would use the normal API or leave a flag in the Task and a setter for the flag (something like stopImmediately). When the loop encountered a true value for this flag it stops processing and completes the run method.
Sometimes if a Thread was started and it loaded a downside dynamic class which is processing with lots of Thread/currentThread sleep while ignoring interrupted Exception catch(es), one interrupt might not be enough to completely exit execution.
In that case, we can supply these loop-based interrupts:
while(th.isAlive()){
log.trace("Still processing Internally; Sending Interrupt;");
th.interrupt();
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
There's a difference between pausing a thread and stopping/killing it. If stopping for you mean killing the thread, then a restart simply means creating a new thread and launching.
There are methods for killing threads from a different thread (e.g., your spawner), but they are unsafe in general. It might be safer if your thread constantly checks some flag to see if it should continue (I assume there is some loop in your thread), and have the external "controller" change the state of that flag.
You can see a little more in:
http://java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
May I ask why you want to kill the thread and restart it? Why not just have it wait until its services are needed again? Java has synchronization mechanisms exactly for that purpose. The thread will be sleeping until the controller notifies it to continue executing.
You can start a thread like:
Thread thread=new Thread(new Runnable() {
#Override
public void run() {
try {
//Do you task
}catch (Exception ex){
ex.printStackTrace();}
}
});
thread.start();
To stop a Thread:
thread.join();//it will kill you thread
//if you want to know whether your thread is alive or dead you can use
System.out.println("Thread is "+thread.isAlive());
Its advisable to create a new thread rather than restarting it.

Categories