Stop a thread like:
new Thread ( new Runnable() {
public void run(){
if ( condition ) return; // this will stop the thread.
}
}).start();
is correct/safe?
Certainly. The Thread will then finish and can be joined with. The thread would also exit if you threw a RuntimeException or just let the code run off the end of the run() method obviously.
A thread stops when it's run() method returns. It doesn't really matter what logic is used inside run() to decide when or how to return. Your code is perfectly correct and safe.
Yes, it is correct and safe...
Related
I have this thread:
myThread = new Thread(new Runnable() {
public void run() {
ServerSocket ss = null;
while (!end) {
final String incomingMsg;
try {
ss = new ServerSocket(2201);
ss.setSoTimeout(15000);
.. some code ...
}
});
myThread.start();
Now i need to stop this with button but nothing work, and i have tried with some code like:
Handler handler= new Handler();
handler.removeCallbacks(myThread);
myThread.interrupt();
But Thread not stopping =(
You can't. Android will automatically stops thread when needed.
What you can do is just stop executing the code inside run() method, Using boolean or something
The accepted answer is not correct. Android does nothing to manage the threads you start, however you start them.
Technically speaking, threads cannot be "stopped". They can interrupted. Interrupting a thread just means that a flag is set, which you, in your thread's implementation, need to consider and exit from the run() method. For example,
Thread t = new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// Do stuff
}
}
});
Then you can call t.interrupt() later on to "stop" your thread.
If you ignore the interrupted flag in your thread's implementation, your thread will never stop. For example, if you replaced // Do stuff above with SystemClock.sleep(Integer.MAX_VALUE) the thread will never exit, regardless of it being interrupted.
Many IO operations implemented in the SDK also pay attention to the interrupted flag, which is why you can interrupt a thread that's participating in blocking IO. See InterruptedException.
You can use .stop(), but it is very bad practice and it can cause you some troubles. Try to add some boolean inside your .run() (like Wizard said)
I want to start a new thread when the line with new Thread executes. I am doing it like this:
new Thread ( new Runnable() {
#Override
public void run() {
.....
}
}).start();
//other code continues here
When the code comes to new thread line it jumps to execute other code. Why?
Well because the new thread almost immediately started running, and the code following the new thread declaration is being executed by the same previous thread.
This is what's happening:
// Main thread running
// Some random code...
new Thread ( new Runnable() {
#Override
public void run() {
// This code will run in another thread. Usually as soon as start() gets called!
}
}).start();
// This code is still being executed by the main thread.
Other than attaching debugger, an easy way to check whether the thread really started running is to put a Log statement inside run()
Simple: because exactly what you want to happen happens!
You create a new thread with new(), and because you call start() immediately on that object, that job starts doing its work.
And your main thread continues its "main" work. It is like: you clap your friend on his shoulder (to signal him: start running) - and now you are asking: "why is he gone?"
That is all there is to this!
I think this is a beginner (me) question, then for you guys is easy to answer.
I have this method:
public void onQuantityTextChange(final int value)
{
new Thread(new Runnable() {
public void run() {
addProductToCart(value);
view.post(new Runnable() {
public void run() {
updateTotals();
}
});
}
}).start();
}
My question is: this peace of code:
view.post(new Runnable() {
public void run() {
updateTotals();
}
is executed only when this addProductToCart(value); method is executed(finished)? or is it more safe to use AsyncTasks with doInBackground() and onPostExecute()?
It is always executed after: addProductToCart(value);
But if that function starts a Thread or AsyncThread or similar then the function will return before that task finishes.
To summarize: nobody can answer without the contents of addProductToCart
That largely depends on whether or not your method addProductToCart(value) starts another thread of its own. If it does, then there's no guarantee as the thread will start and finish as the system sees fit. If not, then you will not call view.post(...) until that thread is complete.
Another thing to watch out for depending on what you're trying to accomplish is the method inside view.post(...) is not guaranteed to run immediately. What this method does is put Runnable objects inside a message queue. This means, this runnable won't execute until the other elements in the message queue execute first. Secondly, the message queue can run at any time meaning even if this is the first Runnable in the queue it will start eventually, but not necessarily immediately.
This is my first question here, so please forgive me if I disobeyed any of the forum rules.
I need my program to wait for 3 seconds and then change the Content View
My code is:
setContentView(R.layout.logout);
new Thread(new Runnable() {
#Override
public void run(){
try {
synchronized(this){
wait(3000);
}
}
catch(InterruptedException ex){
}
}
}).start();
setContentView(R.layout.main);
The program works with no errors, but there is no waiting. When it gets to this part, it just shows the "main" layout without showing the "logout" layout at all.
What is wrong in my approach?
As people noted, don't sleep on or otherwise block the UI thread, but you seem to be aware of this with the new thread you create.
Now for why it doesn't behave as you want:
Right now, you call setContentView(), start a new thread, call setContentView() a second time on the UI thread -- this happens in quick succession with no delay/wait/sleep inbetween. The wait(3000) happens in the new thread you started -- so that new thread starts, waits for 3000ms, then exits. It's an expensive no-op.
You would need to make the second call to setContentView() from inside that new thread's run() method to get the desired effect. Also, you should use sleep() instead of wait() -- wait() is a low-level tool for synchronizing threads while sleep() is the usual "don't continue for X amount of time".
Let me propose a better way:
An arguably nicer and much lighter approch is using Handler.postDelayed() -- this allows you to invoke a Runnable on the UI thread after a delay:
setContentView(R.layout.logout);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main);
}
}, 3000);
Edit to reply to your comment:
Define and find the button before the Runnable as a final variable, this way you can access it later from inside the Runnable.
Please note that to reference the this instance of the surrounding class from inside an anonymous inner class (your new Runnable()), you need to prefix it with the class name of the surrounding class (your Activity class):
final View submitButton = findViewById(R.id.submit_button);
setContentView(R.layout.logout);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main);
// adapt to your actual Activity class name:
submitButton.setOnClickListener(YourClassName.this);
}
}, 3000);
wait() doesn't wait for a certain amount of time, but rather has the current Thread wait for this to do a notify() for a maximum amount of time. What you are looking for, is Thread.sleep().
And at the moment the only thing that will be waiting, is the additional thread you are spawning, not the activity itself. That's why I'd suggest you look at Handler.postDelayed(), CountDownTimer or AsyncTask. Handling threads is very low-level.
Your code not work to sleep UI thread.To sleep UI thread try this code
new Handler().postDelayed(new Runnable()
{
public void run()
{
setContentView(R.layout.main);
}
}, 3000);
Try using Sleep() instead of Wait()
android.os.SystemClock.sleep(3000)
As far as i can understand the wait is happening in the new thread where as you are calling setContentView(R.layout.main) in the current thread.
Try
setContentView(..)
synchronized(this) {
this.wait(1000);
}
setContentView(..)
Please note sleeping or waiting in the UI thread is not a best practice though.
At a certain point of my AsyncTask, after some validations have been done, I need to spawn off another thread to do some other work. So I'd like two background threads at this point, each doing it's own thing (approx 2-3 seconds to execute each). The idea is to maximize performance on dual core processors like Atrix.
Is it acceptable to create another asynctask & execute it from the first one? Can anyone suggest a better way of doing this?
Thanks!
EDIT: I'm wondering what publishProgress() from the second task would even do... since it was not started from an Activity?
Is it acceptable to create another
asynctask & execute it from the first
one?
Yes, but only inside onProgressUpdate() or onPostExecute() since these methods runs on the UI thread. Therefore, start the second AsyncTask on the UI thread by choosing one of the two methods listed above.
I'm wondering what publishProgress()
from the second task would even do...
since it was not started from an
Activity?
It does exactly the same thing, since you are starting it from the UI thread.
If you are looking for a mechanism of executing multiple async tasks, from 3.0 and above it supports a method called executeOnExecutor which will allow you to schedule tasks in parallel on a pool of thread managed by Async Task.
An AsyncTask is useful for doing some background work while communicating with the main thread to handle UI changes. It appears that this is not your case.
Besides, an AsyncTask must be executed from the main thread. From the AsyncTask reference:
There are a few threading rules that
must be followed for this class to
work properly:
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
You can a take a look at this article and see what fits you best.
This can be done using message passing concurrency and a single handler. Proof of concept code follows:
private Handler myHandler= new Handler(){
#Override
public void handleMessage(Message msg){
switch(msg.what){
case 0:
Toast.makeText(Main.this,"Message0", Toast.LENGTH_SHORT).show();
Thread thread= new Thread( new Runnable() {
public void run() {
try {
Thread.sleep(3000);
}
catch(Exception e){}
myHandler.sendEmptyMessage(2);
}
});
thread.setDaemon(true); // <== I am a service provider. KILL ME if the non-daemon thread ConfuseText quits
thread.start();
break;
case 1:
Toast.makeText(Main.this,"Message1", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(Main.this,"Message2", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
break;
}
}
};
I launched the first thread on a button click as in:
ON CLICK HANDLER
threadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Thread thread= new Thread( new Runnable() {
public void run() {
try {
Thread.sleep(1000);
}
catch(Exception e){
}
myHandler.sendEmptyMessage(0);
try {
Thread.sleep(3000);
}
catch(Exception e){
}
myHandler.sendEmptyMessage(1);
}
});
thread.setDaemon(true); // <== I am a service provider. KILL ME if the non-daemon thread ConfuseText quits
thread.start();
}
});
The calls to thread sleep is to mimic a time intensive task.