Thread reusal in Android - java

I have a code in Android, which is resource intensive. It processes a bitmap and then saves it to the sdcard.
Since running it on the main thread took a lot of time, I did it like this:
new Thread(new Runnable() {
public void run() {
//do work
}
}).start();
But, I found that if I invoked this piece of code before the thread had fully executed, the previous thread just got deleted and overwritten with the new task. The sdcard showed only the last image.
So I wrote a static thread as :
Thread t=new Thread(new Runnable() {
public void run() {
//do work
}
};
But, t.start() cannot be called multiple times. (llegalThreadStateException)
What should I do to overcome this?

Spawning a second thread using the code you gave above will work and run both threads in parallel. Something else must be going on to stop it working.
Make sure you have a try-catch around your do work and log any errors. Are both threads trying to write to the same file and the second one failing because it cannot?
For the actual thread you cannot start a thread again once it has exited, instead you need to keep the thread alive and run it in a loop. The thread should go to sleep when it is no longer needed, waiting for a message to arrive giving it new work to do. This can be done using something like a BlockingQueue.
Alternatively rather than managing threads yourself you can use something like a ThreadPoolExecutor and keep sending your Runnables to that.

Related

Java multithreading error [duplicate]

The following code leads to java.lang.IllegalThreadStateException: Thread already started when I called start() method second time in program.
updateUI.join();
if (!updateUI.isAlive())
updateUI.start();
This happens the second time updateUI.start() is called. I've stepped through it multiple times and the thread is called and completly runs to completion before hitting updateUI.start().
Calling updateUI.run() avoids the error but causes the thread to run in the UI thread (the calling thread, as mentioned in other posts on SO), which is not what I want.
Can a Thread be started only once? If so than what do I do if I want to run the thread again? This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.
From the Java API Specification for the Thread.start method:
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
Furthermore:
Throws:
IllegalThreadStateException - if the thread was already started.
So yes, a Thread can only be started once.
If so than what do I do if I want to
run the thread again?
If a Thread needs to be run more than once, then one should make an new instance of the Thread and call start on it.
Exactly right. From the documentation:
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
In terms of what you can do for repeated computation, it seems as if you could use SwingUtilities invokeLater method. You are already experimenting with calling run() directly, meaning you're already thinking about using a Runnable rather than a raw Thread. Try using the invokeLater method on just the Runnable task and see if that fits your mental pattern a little better.
Here is the example from the documentation:
Runnable doHelloWorld = new Runnable() {
public void run() {
// Put your UI update computations in here.
// BTW - remember to restrict Swing calls to the AWT Event thread.
System.out.println("Hello World on " + Thread.currentThread());
}
};
SwingUtilities.invokeLater(doHelloWorld);
System.out.println("This might well be displayed before the other message.");
If you replace that println call with your computation, it might just be exactly what you need.
EDIT: following up on the comment, I hadn't noticed the Android tag in the original post. The equivalent to invokeLater in the Android work is Handler.post(Runnable). From its javadoc:
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* #param r The Runnable that will be executed.
*
* #return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
So, in the Android world, you can use the same example as above, replacing the Swingutilities.invokeLater with the appropriate post to a Handler.
No, we cannot start Thread again, doing so will throw runtimeException java.lang.IllegalThreadStateException.
>
The reason is once run() method is executed by Thread, it goes into dead state.
Let’s take an example-
Thinking of starting thread again and calling start() method on it (which internally is going to call run() method) for us is some what like asking dead man to wake up and run. As, after completing his life person goes to dead state.
public class MyClass implements Runnable{
#Override
public void run() {
System.out.println("in run() method, method completed.");
}
public static void main(String[] args) {
MyClass obj=new MyClass();
Thread thread1=new Thread(obj,"Thread-1");
thread1.start();
thread1.start(); //will throw java.lang.IllegalThreadStateException at runtime
}
}
/*OUTPUT in run() method, method completed. Exception in thread
"main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
*/
check this
The just-arrived answer covers why you shouldn't do what you're doing. Here are some options for solving your actual problem.
This particular thread is doing some
calculation in the background, if I
don't do it in the thread than it's
done in the UI thread and the user has
an unreasonably long wait.
Dump your own thread and use AsyncTask.
Or create a fresh thread when you need it.
Or set up your thread to operate off of a work queue (e.g., LinkedBlockingQueue) rather than restarting the thread.
What you should do is create a Runnable and wrap it with a new Thread each time you want to run the Runnable.
It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.
It is as you said, a thread cannot be started more than once.
Straight from the horse's mouth: Java API Spec
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
If you need to re-run whatever is going on in your thread, you will have to create a new thread and run that.
To re-use a thread is illegal action in Java API.
However, you could wrap it into a runnable implement and re-run that instance again.
Yes we can't start already running thread.
It will throw IllegalThreadStateException at runtime - if the thread was already started.
What if you really need to Start thread:
Option 1 ) If a Thread needs to be run more than once, then one should make an new instance of the Thread and call start on it.
Can a Thread be started only once?
Yes. You can start it exactly once.
If so than what do I do if I want to run the thread again?This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.
Don't run the Thread again. Instead create Runnable and post it on Handler of HandlerThread. You can submit multiple Runnable objects. If want to send data back to UI Thread, with-in your Runnable run() method, post a Message on Handler of UI Thread and process handleMessage
Refer to this post for example code:
Android: Toast in a thread
It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.
I have had to fix a resource leak that was caused by a programmer who created a Thread but instead of start()ing it, he called the run()-method directly. So avoid it, unless you really really know what side effects it causes.
I don't know if it is good practice but when I let run() be called inside the run() method it throws no error and actually does exactly what I wanted.
I know it is not starting a thread again, but maybe this comes in handy for you.
public void run() {
LifeCycleComponent lifeCycleComponent = new LifeCycleComponent();
try {
NetworkState firstState = lifeCycleComponent.getCurrentNetworkState();
Thread.sleep(5000);
if (firstState != lifeCycleComponent.getCurrentNetworkState()) {
System.out.println("{There was a NetworkState change!}");
run();
} else {
run();
}
} catch (SocketException | InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Thread checkingNetworkStates = new Thread(new LifeCycleComponent());
checkingNetworkStates.start();
}
Hope this helps, even if it is just a little.
Cheers

Java Thread only works once [duplicate]

The following code leads to java.lang.IllegalThreadStateException: Thread already started when I called start() method second time in program.
updateUI.join();
if (!updateUI.isAlive())
updateUI.start();
This happens the second time updateUI.start() is called. I've stepped through it multiple times and the thread is called and completly runs to completion before hitting updateUI.start().
Calling updateUI.run() avoids the error but causes the thread to run in the UI thread (the calling thread, as mentioned in other posts on SO), which is not what I want.
Can a Thread be started only once? If so than what do I do if I want to run the thread again? This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.
From the Java API Specification for the Thread.start method:
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
Furthermore:
Throws:
IllegalThreadStateException - if the thread was already started.
So yes, a Thread can only be started once.
If so than what do I do if I want to
run the thread again?
If a Thread needs to be run more than once, then one should make an new instance of the Thread and call start on it.
Exactly right. From the documentation:
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
In terms of what you can do for repeated computation, it seems as if you could use SwingUtilities invokeLater method. You are already experimenting with calling run() directly, meaning you're already thinking about using a Runnable rather than a raw Thread. Try using the invokeLater method on just the Runnable task and see if that fits your mental pattern a little better.
Here is the example from the documentation:
Runnable doHelloWorld = new Runnable() {
public void run() {
// Put your UI update computations in here.
// BTW - remember to restrict Swing calls to the AWT Event thread.
System.out.println("Hello World on " + Thread.currentThread());
}
};
SwingUtilities.invokeLater(doHelloWorld);
System.out.println("This might well be displayed before the other message.");
If you replace that println call with your computation, it might just be exactly what you need.
EDIT: following up on the comment, I hadn't noticed the Android tag in the original post. The equivalent to invokeLater in the Android work is Handler.post(Runnable). From its javadoc:
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* #param r The Runnable that will be executed.
*
* #return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
So, in the Android world, you can use the same example as above, replacing the Swingutilities.invokeLater with the appropriate post to a Handler.
No, we cannot start Thread again, doing so will throw runtimeException java.lang.IllegalThreadStateException.
>
The reason is once run() method is executed by Thread, it goes into dead state.
Let’s take an example-
Thinking of starting thread again and calling start() method on it (which internally is going to call run() method) for us is some what like asking dead man to wake up and run. As, after completing his life person goes to dead state.
public class MyClass implements Runnable{
#Override
public void run() {
System.out.println("in run() method, method completed.");
}
public static void main(String[] args) {
MyClass obj=new MyClass();
Thread thread1=new Thread(obj,"Thread-1");
thread1.start();
thread1.start(); //will throw java.lang.IllegalThreadStateException at runtime
}
}
/*OUTPUT in run() method, method completed. Exception in thread
"main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Unknown Source)
*/
check this
The just-arrived answer covers why you shouldn't do what you're doing. Here are some options for solving your actual problem.
This particular thread is doing some
calculation in the background, if I
don't do it in the thread than it's
done in the UI thread and the user has
an unreasonably long wait.
Dump your own thread and use AsyncTask.
Or create a fresh thread when you need it.
Or set up your thread to operate off of a work queue (e.g., LinkedBlockingQueue) rather than restarting the thread.
What you should do is create a Runnable and wrap it with a new Thread each time you want to run the Runnable.
It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.
It is as you said, a thread cannot be started more than once.
Straight from the horse's mouth: Java API Spec
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
If you need to re-run whatever is going on in your thread, you will have to create a new thread and run that.
To re-use a thread is illegal action in Java API.
However, you could wrap it into a runnable implement and re-run that instance again.
Yes we can't start already running thread.
It will throw IllegalThreadStateException at runtime - if the thread was already started.
What if you really need to Start thread:
Option 1 ) If a Thread needs to be run more than once, then one should make an new instance of the Thread and call start on it.
Can a Thread be started only once?
Yes. You can start it exactly once.
If so than what do I do if I want to run the thread again?This particular thread is doing some calculation in the background, if I don't do it in the thread than it's done in the UI thread and the user has an unreasonably long wait.
Don't run the Thread again. Instead create Runnable and post it on Handler of HandlerThread. You can submit multiple Runnable objects. If want to send data back to UI Thread, with-in your Runnable run() method, post a Message on Handler of UI Thread and process handleMessage
Refer to this post for example code:
Android: Toast in a thread
It would be really ugly to do but you can Wrap a thread with another thread to run the code for it again but only do this is you really have to.
I have had to fix a resource leak that was caused by a programmer who created a Thread but instead of start()ing it, he called the run()-method directly. So avoid it, unless you really really know what side effects it causes.
I don't know if it is good practice but when I let run() be called inside the run() method it throws no error and actually does exactly what I wanted.
I know it is not starting a thread again, but maybe this comes in handy for you.
public void run() {
LifeCycleComponent lifeCycleComponent = new LifeCycleComponent();
try {
NetworkState firstState = lifeCycleComponent.getCurrentNetworkState();
Thread.sleep(5000);
if (firstState != lifeCycleComponent.getCurrentNetworkState()) {
System.out.println("{There was a NetworkState change!}");
run();
} else {
run();
}
} catch (SocketException | InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Thread checkingNetworkStates = new Thread(new LifeCycleComponent());
checkingNetworkStates.start();
}
Hope this helps, even if it is just a little.
Cheers

Restarting a thread after it has been left

I have thread which contains a loop
while(isRunning){
}
isRunning is a Boolean variable with the value true, when some clicks on a button it gets false and so it leaves the loop and the run() function of the thread.
I want to create another button that on click it will reenter the run() function.
I am not sure if when I leave the run() function the thread dies or just stops.
I have tried using thread.run() but it didnt work.
Also I have looked for an answer in other's people questins about this matter but nothing seemed to help me. Thanks for the help
When a thread is finish processing it's code, There's no way of restarting it. You can either:
Create a new thread and pass the Runnable to that thread.
If you need to use that run() method often, use an Executor. You can use Executors.newSingleThreadExecutor(), which will supply you with a worker thread. (Reusable thread).
class Example {
static ExecutorService executor = Executors.newSingleThreadExecutor();
static Runnable run = new Runnable() {
public void run() {
}
};
public static void main(String[] args) {
//anytime you wanna run that code..
executor.execute(run);
}
}
If your thread runs to its end, it stops.
It will remain there for you to collect its return status until the thread is cleaned up.
To restart within the same thread, you need an extra control flow.
For instance:
while (restarted) {
while (isRunning) {
}
// Wait for a restart or end click
}
That is what so called worker threads in a thread pool do, which are intended for maximum performance.
But logically, you will probably simply want to create a new thread object and start that one.
new Thread(p).start();
Please read through java concurrency tutorial.
http://docs.oracle.com/javase/tutorial/essential/concurrency/
Just Maybe, guarded blocks might be useful for your case but your case is a little vague to recommend anything specific.
http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

ANDROID - While loop inside Thread

I create a thread to process some queue data. Inside the thread there is a unlimited while loop. when loop is working, the interface always freezing.
Im confused about this, I've created the thread, but why it still freezing ??
Thread queue = new Thread(new Runnable() {
public void run() {
while(true) {
...
}
}
});
queue.start;
Any solution for this problem ?
Its not just your interface slowing down, in fact your phone will be too because you are consuming (unnecessarily wasting) all the processing powers in a while loop. For better approach, use Handler and/or AsyncTask or at least use Thread.sleep inside while-loop in your thread.

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