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.
Related
I want to ensure that I don't slow down my app's startup time and need to start a background task that's unrelated to user input--for instance, filling a cache.
If I start an AsyncTask from my onCreate method, when will the doInBackground method actually begin to execute? (Assume a single core device)
Is it possible that Android could schedule it before onCreate/onResume has completed, or is it smart enough to recognize that the background thread shouldn't run until the UI thread is completely finished?
If you look at AsyncTask source code you will see that it is just using ThreadPoolExecutor or serial executor for running tasks. Default internal behavior depends on Android version (from AsyncTask docs):
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
But anyway doInBackground execution is not connected with Activity lifecycle so AsyncTask may be executed at almost any time. This depends only on how many tasks you have already started, on default Executor which is used by AsyncTask and on thread scheduler.
I usually use AsyncTasks in onCreate() like this:
private MySuperSpecialTask mySuperSpecialTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(...);
// [...]
mySuperSpecialTask = new MySuperSpecialTask();
mySuperSpecialTask.execute();
}
#Override
protected void onDestroy() {
super.onDestroy();
if (mySuperSpecialTask != null) {
mySuperSpecialTask.cancel(true);
}
}
This makes sure that everything is initialized before the task gets started.
actually strictly speaking there is no execution order of your UI code and starting the asynctask I found out. Normally one does not experience this, however, if your UI thread takes longer for some reason, eg waiting for external input etc, the asynctask might have gotten started BEFORE UI code has finished.
Writing UI code is just a request to the Android system and this waits in the execution loop. So if asynctask starts before that because there are enough ressources (or as mentioned UI thread is delayed for whatever reason) there is no execution order guarantee.
One easy way to enforce this is - in case you don't mind and you can be sure that it is suffiencient - delay the starting of the asynctask with ScheduledExecutorService or a "cleaner" way would be to implement some kind of gate keeper that waits for a flag to be set to true and then start the asynctask. Or you may even have a while-loop at the beginning of your asynctask that waits for the flag to be set to true, like in many communication situations with external devices.
The flag would be set to true AFTER you can be (normally) sure that your UI has finished.
There have been a number of questions regarding the proper usage of Threads vs. Handlers vs. AsyncTask. (like here & here)
Those questions nicely addressed the question of when to use what. My question is more about the performance implications in certain types of cases.
As an example, I often see other people write code in which they use Threads simply to be able to schedule some code execution for the future. Whenever, I see this, I instinctively feel like refactoring the code to use a Handler and just a post a delayed runnable.
Here's an example where a Thread is used to update the seekbar for some media playing with a mediaplayer and then the way I would do it.
what I see a lot:
if (positionTracker != null && positionTracker.isAlive()
&& !positionTracker.isInterrupted()) {
return;
}
positionTracker = new Thread(new Runnable() {
public void run() {
int currentPosition = 0;
int total = player.getDuration();
while (player != null && CurrentPosition < total) {
try {
Thread.sleep(1000);
currentPosition = player.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
if (someListener != null) {
someListener.onEvent();
}
}
}
}, "position tracker thread");
positionTracker.start();
And the way I like to do it:
Runnable trackPositionRunnable = new Runnable() {
#Override
public void run() {
currentPosition = player.getCurrentPosition();
if (someListener != null) {
someListener.onEvent();
mHandler.postDelayed(this, 1000);
}
}
};
mHandler.post(trackPositionRunnable);
Obviously, my preferred way is a bit easier to read and more concise. But what are the performance implications? Is one way method better, in terms of performance, than the other? If so, why?
Each method depends on what you plan on doing in that Runnable as to whether it will be useful or not. The biggest difference between them all is whether you plan on touching the UI or not. In Android you can't touch UI components off the UI thread (your example of media player is breaking this rule with raw Thread). Because of this rule that immediately divides what you can and can't do with each method. Performance differences between these methods is negligible because time spent running your background job is going to trump any differences between them.
Handler typically use another background thread to execute logic in, but it depends which thread constructed the Handler. If the Handler was constructed on the UI Thread (in response to callback onSomething) then your Runnable will run inside the UI Thread making it ok to touch UI Components. However, if you created it off the UI thread Runnables posted to it CANNOT touch UI components. The downside to Handlers created on the UI thread means you aren't doing these in the background so if a job takes a long time to run it will lock up the UI until its done. While Handlers run from non-UI threads will fix the any issue of locking up the UI. They take more work to setup and you still have to contend with how to safely update the UI in response to your background job (ie you still have to post another runnable back to the UI Thread if you want to update the UI).
Raw threads won't lock up the UI because they are running independently from the UI thread, but you can't touch UI components on them. That means you'll have to execute any code you want to update the UI with back on the UI thread which means more code needs to be written to get the UI thread to run it. This can be very complex. Raw threads should really be avoided because of the complexity in using them.
The most common example of background tasks is waiting for a response from the server. Most libraries block until the server sends a response which means you can't call them on the UI thread or else your user will be blocked from doing anything until the server returns a call. Not only will they be blocked, but the UI can't update itself to show a spinner or otherwise look alive. This is best to push off to a background thread. Technically Handlers and Threads can do this, but Handlers have to be constructed specially so they will use a true background thread.
This is where AsyncTask trumps Handlers because it does both true background jobs and UI updates. It has a section for doing some long running operation in the background and it has a section for updating the UI from the UI thread when its done. It even has an optional progress section so you can provide any intermediate progress to the UI while the task is running. The downside of an AsyncTask is that they must have an end. Background jobs that continue to run to periodically check if something has happened, sleep and check some more aren't conducive to the AsyncTask model. However, that's not to say you couldn't use a Handler to periodically kick off AsyncTask, but just for the completeness of the discussion I mention that.
In the end using raw Threads isn't all that easy or even "better" because Handlers can do pretty much anything that Threads can do with less code. But, Handlers are tricky in determining which thread the Runnable is executing on. Most often it's the UI thread, and technically setting it up to use a non-UI thread is tricky. Both options suffer from the UI update issues in that you have to do extra work to run UI jobs at the end of true background jobs. AsyncTask is really my preferred method for doing background jobs.
It is not Handler vs Threads. They are quite different things:
Thread: Is the old Java class that implements a thread of execution. As other parts of the Java APIs they are also available on Android. Notice than in late versions of the Java language they were superseeded by the Executors framework, so the recommended practice is to use Executor/Runnable, but due to it's simplicity Threads are still used sometimes.
Handler: This class is available only in Android, and it is mostly a mechanism to communicate with an existing Thread. You send the target thread Messages or Runnables, and you can also schedule this communication.
You usually need a Handler when you need to send something to a thread. This "something" can be, for instance, encapsulated data to be processed, or a Runnable to be executed in that thread. Every handler is usually associated to the current thread at the time of instantiation, unless you use a more exotic constructor. A typical use case is to schedule a repetitive task in the main thread (which is the UI thread). Notice that for scheduling a one-shot task there's an easiest way: Activity.runOnUithread.
Now for a background task that needs to be run in a thread different than the main one: in both approaches you'll have a thread running, but creating a handler means that Android will start a new Message Queue for that thread, which is something regular threads do not need to have, and because of this there will be some overhead. Thus if you need to start a thread that can run isolated without receiving information, i'd say the simple Thread is preferred. But if you need an execution queue to schedule Runnables you can choose between a Timer, an Executor, a "handled" thread, or even AlarmManager. The advantage of Handlers is that they can be attached to any already existing thread in your app, while Timer and Executors will internally launch a new dedicated thread when they are set up.
Correctness: Your first example is fraught with peril, since a MediaPlayer must be created on a thread with its own Looper and operations from any other thread may cause errors. Similarly, since your someListener.onEvent() is presumably updating a UI, it had better know to post to a handler on the UI thread anyway.
Performance: I have no measurements to offer, but in your example, the runtime cost is (thread switching) + (handler overhead), versus just (handler overhead). So for any thread switching overhead > 0, the threads are more expensive. On the other hand, if your entire application is coded in your favored style, and any piece of your code is slow and synchronous, you just made your application feel laggy.
Which is why anything potentially slow or synchronous needs to head toward the thread (or service) style, despite feeling more complex and error-prone. Your particular MediaPlayer example is not a perfect poster child for making this case.
If you're dealing with threads, I suggest that you use a handler together with it:
Handler handle = new Handler();
Thread new Thread()
{
#Override
public void run()
{
try
{
handle.postDelayed(new Runnable()
{
#Override
public void run()
{
"your code goes here"
}
},delay);
}
catch(Exception e)
{
e.printStackTrace();
}
};
}
That way you can delay the execution for as long as you want, or you can use post and Thread.sleep(delay), which I prefer these days.
I'm have a game that's uses SurfaceView implementation to display the objects.
I have a thread which draws the SurfaceView time-to-time to the screen.
The game is running completely.
Unfortunately, it needed to have a pause function whenever the game is interrupted.
Well, I know that I need to manipulate onResume and onPause.
But I can't get it right. The error points me back to surfaceCreated where I start the thread telling me that the thread has started already. I tried using the resume and suspend on the onResume and onPause respectively but nothing changed.
How can I achieve this?
I have already done how the objects location would be save using File-I/O handling.
Thanks in advance.
This is what I did:
#Override
public void surfaceCreated(SurfaceHolder arg0) {
if (thread.getState() == Thread.State.TERMINATED){
CreateThread(getHolder(),getContext());
}
thread.setRunning(true);
thread.start();
}
In CreateThread you should have the thread = new MyThread(...);
the setRunning (boolean mRun) use a boolean to start/stop the run function (I think I was inspired by the LunarLander);
If you want to use properly the onPause/onResume don't put the variables used by your thread inside the thread (as done in LunarLander). I suggest you to do like that:
// Variables declarations
public MyGameThread CreateThread(...){
thread = new MyGameThread(holder, context, new Handler() {
// and so on....
});
}
When you pass through the onPause/onResume, your thread will be destroyed and reneweled but if you put your variables outside it, you can continue to use them after.
If you have something important to preserve, use one of this options:
SharedPreferences: an xml will be created and saved locally with variables that persist even after the end of the app;
a SQL db if you would manage more than 5-10 variables because in this case the use of the former option would be difficult.
Actually it's not recommended to stop a thread by yourself, the stop() method is deprecated. The simplest solution is to use a flag in your while loop inside the thread's run() method. When you need to "stop" the thread, you just drop the flag to false and the thread won't do anything anymore, despite it will keep running. Android will stop your thread when it's needed. Hope this helps.
Without knowing the ins and outs of your code.
To "Pause" a thread you can implement functionality like so:
while(! this.isInterrupted())
if(!paused)
{
... Do something ...
} else { try { Thread.sleep(100) } catch (InteruptedException ie) {} }
This is depending if Do something is invalidating your surface view or otherwise controlling progression in your app. An accessor to paused should allow you to pause and resume your thread without getting caught up in any other bit of architecture.
I'm unsure if you've got one or two threads in this question, I'm assuming 2. You need to do three things when you call onPause:
1 - Save the state of the application (all game variables, states, etc)
2 - Kill the surfaceView by calling suspend.
3 - Kill the other thread (we'll call it Thread B).
Killing of Thread B is your problem I think. You want to interrupt the thread and tell it to quit, or else when you call onPause your thread will still be doing its thing. Then, when you go back into the game, the thread will try to be created again which causes the problem. There are 2 ways to kill a thread properly:
In the while() loop of your thread, have a boolean 'run' which while(run) will execute the code. When you change run to false, the thread exits.
If your thread sleeps (I assume it might do since its a game and will be running w.r.t time), catch the InterruptedException and then quit there. When you want to kill the thread, you throw the exception to the thread.
The first one is by far the easiest.
I'm going nuts here.
I want a simple thing - I have a long task (fetching several data objects from the web) and I want the ability to cancel it.
I tried a lot of things (a lot) and nothing works
The flow goes like this:
the user click on a button
I start the work (I tried with AsyncTask, Service, IntentService and Looper)
the task takes care of everything including adding ongoing notification for progress updates
the intent in the notification has a call for a new activity that her only purpose is to cancel the ongoing task
in the cancelActivity I tried to call stopService() for Service/IntentService or do
Looper.quit() for the Looper (I don't remember what I tried for AsyncTask, not sure if there is such api for canceling it)
In my point of view the best option will be using IntentService (I could have several task lining up and IntetService will do it in order like I want) but
I'm open to suggestions for any type of implementation - I don't care what the code will be, just that I will have the option to cancel the task
Thank you in advance for your help
Dror
(I'm off to bed - 8 hours on the same issue is just too much)
It does not matter what specific operation you use to stop the task if you don't recognize the stop condition in your background logic. The only way to cleanly accomplish it is if background worker stops and exits in good faith.
There are few possible scenarios and solutions that you can use for canceling background work.
Background thread executes many short steps (for example computation with some loops). In this case, check some flag (could be isInterrupted()) between operations and exit if this flag indicates that operation must stop.
Background thread is waiting on monitor. Call interrupt() on background thread, catch exception in in exception handler make appropriate steps to finish this task cleanly and exit.
Background thread is waiting on IO. This use case is very hard to solve in general case. If you use some socket, you can try closing this socket externally and catch the exception. In worst case scenario, you can just abandon the thread in the state that if it ever returns from IO it knows that it is canceled and IO results must be discarded. If you do it often - you will run out of memory, so I would not really recommend it.
In any case, there is no way (except killing the thread which is really bad) to stop your task if it does not know about possibility of being stopped.
Ok, i manged to do something close to what I want.
I'm using IntentService that will queue my task. each new task is AsyncTask. the AsyncTask starts with sending notification with pendingIntent for cancelActivity.
When clicking on the notification the user gets a warning popup about stopping the task. If he clicks yes than I do stopService() on my IntentService.
In the IntentService I added:
#Override
public void onDestroy() {
currentTask.cancel(true);
if (mNotificationHelper != null)
mNotificationHelper.completed();
super.onDestroy();
stopSelf();
}
in the AsyncTask I added:
#Override
protected void onCancelled() {
isCanclled = true;
httpClient.getConnectionManager().shutdown();
mNotificationHelper.completed();
if (mAsyncTaskListener != null)
mAsyncTaskListener.AsyncTaskCanceled();
}
so that will drop all the connection currently in motion. In the actual code that do the work I need to catch the exception for connection shutdown and handle it
so in the end I'm not actually stopping the AsyncTask/Service but rather exposing the httpClient so I will be able to drop the connection in asynchrony why.
I think is a bit ugly but I got no other way
thank you all
In my app I have a background task (using AsyncTask) that downloads stuff from a web site.
This task can be called from two separate activities, and it is possible to call it twice. So in "activity1" the background task "update" is called, and runs for a while (it takes something like 5-10 seconds usually).
Then while it's running, user switches to "activity2" and runs "update" again.
This gives problems: either a crash when both try to clear the database (command: DELETE FROM table) at the same time, causing a "database locked" error. Or they try to put the same item in the database causing a duplicate.
I've tried to solve this by setting a static boolean flag to true when a task is active.
When the task is called, it will check for this flag, and if true (i.e. the same task running on another thread) it goes into a wait loop using a handler until this flag clears, and then returns. This to make sure that when the background task returns, the update has been done. I have to use a Looper for that: this sometimes fails with an error "can create only one looper per thread". And I really have it in a way that only one looper can be started, this is the offending code, which appears at the start of the background task:
if (active) {
Looper.prepare();
handler = new Handler();
handler.postDelayed(new Runnable() {
int count = 0;
#Override
public void run() {
if (active) {
count++;
if (count < 1000)
handler.postDelayed(this, 100);
}
}
}, 100);
Looper.loop();
active = false;
return "done";
}
And to make matters worse it often seems to hang in this loop, without returning.
How to solve such a situation?
Why don't use synchronization instead? It sounds like a concurrency issue. Why don't you make sure that if the first background task is running then the second background task is sleeping until the first one is finished.
Or ensure somehow, that if the user switches to Activity number 2, the background task from activity number 1 is cancelled.
Instead of the AsyncTask you can consider to use IntentService. Have a look at the Android Service concept. The IntentService class ensures that only one request will be processed at one time.
I found this answer very useful during implementing IntentService with Activity callback communication.
Database locking issues solved by wrapping it into a ContentProvider. Besides problems with a method being called again before the previous instance was finished, I had the issue of different methods running in different background threads clashing while trying to write to the database.
Officially designed to allow for sharing data between apps, it also works great for sharing data between threads in a single app. The ContentProvider will make sure that no locking issues occur.