I have a class that extends the Thread class and has its run method implemented as so.
public void run(){
while(!terminate){
if(paused){
Thread.yield();
}else{
accummulator++;
}
}
}
This thread is spawned from the onCreate method.
When my UI is hidden (when the Home key is pressed) my onPause method will set the paused flag to true and yield the tread. However in the DDMS I still see the uTime of the thread accumulate and its state as "running".
So my question is. What is the proper way to stop the thread so that it does not use up CPU time?
It is actually bad practice to keep a thread running after onPause. The reason is that after onPause your application may drop out of memory at any time without your being able to know, therefore you will not be able to clean up after yourself.
The proper way to do it is stopping the thread onPause and recreating it onResume. If you need state you can use Android's built in saveState methods or settings or whichever to keep that.
Even though you're calling thread.yield(), you're inside of a while() loop which is probably looping thousands of time per second, each time calling .yield() but the fact that it's looping out of control means that it's using up resources. If you put a Log.d message in there you'll see what I mean.
I recommend using a Thread.sleep() instead of Thread.yield(). The reason being, while a thread is sleeping it is yielded. Plus with the sleep you get the added benefit of slowing down the while() and not using up resources. A sleep interval of 500ms should be sufficient =)
Your paused variable is most likely being cached thread-locally. This is because it's only being read and not changed in the loop. So what is happening is that compiler/interpreter/jitter optimizes by only reading the variable once and then only executing the else branch. You need to mark that field as volatile for the pause variable to be read every iteration through the loop. Check out the documentation of the volatile keyword. Here's some info about threading and some info about synchronization and concurrency.
Related
I would like to make use of the universal tween engine in my pure android app, and understand that I will need to put a loop somewhere which will update the tweenmanager every frame. I have used this before in game projects where i have access to the game loop provided but in the case of a pure android application, where would I create this loop and what is the best way to handle this as my app is opened/closed/paused/resumed etc?
Am I best creating a new thread in the onResume method for each activity and starting the loop there and ending the loop in the onPause method? or is it better to create a class that acts as a sort of "Activity manager" and is always available? if so how would I do this?
I found some useful documentation on this at https://code.google.com/archive/p/java-universal-tween-engine/wikis/AndroidUI.wiki and It seems the 'correct' way to achieve this is to create a new loop for each activity in onResume() and end the loop in onPause()
There is an API available starting in API level 16 called Choreographer. This is the thing that keeps the main thread pumping events at 60 frames per second. You can register a callback to be executed with the next frame, then within that callback, register to run it again at the next frame. This is the most reliable way to get called at every frame with near-perfect timing (as long as the main thread is not being blocked in a way that would case frame loss).
Your callbacks will all be called on the main thread, so be careful yourself about blocking the main thread. So keep your work super fast.
In my app, the activity starts a thread which download images from server. There are more than 30 images. While downloading, the user can switch to another activity. So I want that the thread should stop doing whatever it is doing. I have used mThread.interrupt() method in onDestroy(), but it did not worked. How to do that?
I can suggest simpler&safer approach to handle this
Use common value across your app;
SharedPreferences or inside Application context
Key=IsStopDownload
Value= True / False
part.1)
in Application context (MyApplication)
private boolean isAppActive = false;
public void setAppState(Context context, boolean state) {
isAppActive = state;
// note: you can also store this in SharedPreferences
}
public boolean getAppState(Context context) {
return isAppActive;
// note: you can also load this from SharedPreferences
}
part.2)
Activity onResume and onPause are the guaranteed places to identify state of your activity.
onResume -> activity is active
onPause -> activity is not active
part.3)
let your thread check the activity state and if not active, it can stop itself, thats safer then making external interrupt. threads can act weird when interrupted from outside, it is safer to break the loop from inside.
e.g.
((MyApplication)context.getApplicationContext()).getAppState(context);
if thats false, thread stops itself
hope this helps...
---
Social Coding #AspiroTV
When user will switch the activity , this one will not destroyed but paused so trying your code is onPause() might work .
First of all, you're probably much better using an AsyncTask than a Thread, so, personally, I wouldn't use a Thread at all. In my humble opinion and small experience, in that situation where you're using them, they grow and grow until you have spaguetti code.
And second, as Dr. Nik said, this task is typically better served using a Service. It's is, in my opinion, the best and safer thing you can do.
I would point out several reasons why you should use one:
The service does not need to stop because the activity goes away.
Services are very easy and quick to implement. And the notification code for completion is also easy.
You are downloading images, and it's always better to do the job at once if you can, to save bandwidth and connection time for the user and cache images locally. This used to be worse because today cell phones are full fledged computers. But it's always important to code for efficiency. Therefore, IMHO, you should keep the need for a connection as small/quick as possible.
Finally, even using AsyncTasks inside an activity demands a tricky (simple, but still tricky) code to catch and detach the task when the Activity is going away, and a check for nulls when it's coming back. Since you're downloading images, and that can take a time and it's very possible that the user may demand an orientation change (turn the device to landscape), you will need that. Search stackoverflow for "orientation change asynctask" for examples.
There are probably other reasons, too, but those are on the top of my head right now. And of course, it's my opinion.
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 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.
I have a main game thread but when the target score is achieved I have an activity that is launched called StageCleared which basically displays the stats to the user of their performance and then they can press a continue button to carry on with the game. This should switch focus back to the running thread that should continue execution, and thus display the game activity (with parameters i update after StageCleared has exectued).
It was suggested I use a package visible object that calls wait() on itself in the main game thread, and then notify() on itself from StageCleared in order to continue execution. My first problem is I can't seem to declare a package visible object that can be seen by all the classes in my package? Secondly, is this the best way to achieve what I'm intending to do or is there a better way?
Many thanks
To enable package visibile, leave the modifier blank:
static boolean mVarname = true;
mVarname is visible inside the package.
I work with a run flag to enable if the loop should do something or just "idle". I, too, dont know if this is a good way to do it :)
Use FutureTask and Executor, check it out in Java API.
It's like, you define the operation and FutureTask, and it'll wait until the task is completed.
Easier than wait()