I have a Thread which runs my game loop. I want to be able to run this game loop each time I start a new game. But since the threads in Java can only be started once, how can I do this?
Create a new Thread around the same Runnable instance and start that.
Since you want the Thread that runs the game loop to keep running it, you need to code it something like this:
public class GameLoop implements Runnable {
...
public void run() {
while (gameNotFinished) {
// do stuff
}
}
}
If that is not working, then the chances are that the run() method is dying because of an exception that you are not catching / logging, and therefore not noticing.
1. When you say that "you need to run a thread", i means you want to start a sub-task on a separate thread.
2. Now if you mean this certain sub-task, then please prefer to run a new thread.
3. As you said But since the threads in Java can only be started once
This means that when a thread (thread of execution) completes its run() method, then the Thread object associated with it permanently looses its threadness, right....
But if this thread is from a pool, then the pool itself manages the Thread objects and its reused. Try using Executors from java.util.concurrent package.
1) The short answer is precisely what SLaks already said: just "...create a new thread around the same runnable instance and start that."
2) I think you might be confused about the distinction between the everyday meaning of "start", and the semantics of the Java Thread method "start()". This tutorial might help:
http://www.geom.uiuc.edu/~daeron/docs/javaguide/java/threads/states.html
3) Should you wish to re-use the same thread, you can use the methods "wait()" and "resume()":
http://www.javabeginner.com/learn-java/java-threads-tutorial
Related
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
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
I am having a problem understanding the differences between some kinds of making a tread loop.
one is (a rough demonstration):
Thread thread=new Thread("name") {
public void run()
{
// do stuff
}
}.start();
the second is:
making a class that imlpements runnable,
creating a thread :
Thread thread = new Thread(this,"name").start();
and the third (in android, i don't if it can work some how else):
making a Handler,
creating a Runnable,
and having handler.postDelayed(runnable), or handler.post(runnable).
I don't understand what's the difference, the only thing i did notice is that making a Thread makes the run loop work a lot faster than using a handler.
could some one explain to me what's the difference between them and what should i use to what?
The first and the second way are exactly the same. It is just different constructions that can be more useful in different situations. Note that Thread implements Runnable and may just run himself in the new thread.
The third way is a little bit misinterpreted by you. Handler runs Runnable in the thread where the Handler was instantiated (unless you specify another looper). If you created your Handler in the UI thread it will run Runnable in the UI thread as well. And as a result it may work slower.
Ok.... Let me try to explain this the best I can....
Also: this is for a mod within minecraft.
Okay, so I created a thread object
public static Thread KillThread = new Thread();
Then in the constructor of my main class which is called when the game(Mine craft starts) I have
KillThread = new Thread(new KillAuraThread());
KillAuraThread is the name of the class that is the thread..
So I created a thread now. Is where it's pissing me off
The thread will run for exactly 1 second, and It can not be running multiple times or it will ruin the point of the delaying and threading.
if(KillAura.enabled && !KillThread.isAlive())
{
System.out.println("Go AURA!");
try
{
KillThread.start();
}catch (Exception e)
{
e.printStackTrace();
}
}
That is called every tick within the game where it would send position updates and such.
Now here is where I'm having the problem. Once the thread starts it becomes "alive" and when it ends it is no longer "alive". But can threads only be started once? because after the first run it's no longer working? And ideas? Links?
Yes Threads can only be started once, you cannot reuse a Thread object.
It is never legal to start a thread more than once. In particular, a
thread may not be restarted once it has completed execution. See java.lang.Thread.start()
Regardless of this fact, do not use the Thread.State for thread lifecycle management.
You're right, threads can run only once and it's illegal to start/run a thread more than once. You should consider using a while loop to keep your thread alive.
Instead of directly dealing with Threads, you should be using the classes inside the java.util.concurrent package to schedule a fixed task at regular intervals which is apparently what you're trying to do. Take a look at ThreadPoolExecutor.
I am storing a bunch of threads objects in an arraylist. I want to be able to start these threads at random. Same thread can be started more than once. Before I start a thread object, I check on whether the thread is alive, and if they have either of NEW or TERMINATED status. This restriction because, I don't want to disturb the 'busy' threads. Now, for NEW threads, this works fine. But for TERMINATED thread, I get an exception.
When a thread ends, shouldn't it go back to being 'new'? Or are threads 'disposable' - like use once and done?
As it says in the documentation for Thread.start(), "It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution."
It is better for you to keep hold of Runnable instances and implement your own logic for keeping track of when the execution of each one of them finishes. Using an Executor is probably the simplest way to run the Runnables.
You should probably be using the awesome stuff provided in java.util.concurrent. Based on your description, ThreadPoolExecutor sounds like a good thing to check out.
This is the way I did it
class GarbageDisposalThread extends Thread {
public void start() {
try {
super.start();
} catch( IllegalThreadStateException e ) {
this.arrayList.remove(this);
this.arrayList.add( new GarbageDisposalThread( this.arrayList ));
}
}
private GarbageDisposalThread() {
}
public GarbageDisposalThread( ArrayList<Whatever> arrayList ) {
this.arrayList = arrayList;
this.start();
}
public void run() {
// whatever the code
}
private ArrayList<Whatever> arrayList = null;
}
that's it!
you can change the code according to your needs :P
Java threads cannot be restarted.
From the javadoc:
It is never legal to start a thread
more than once. In particular, a
thread may not be restarted once it
has completed execution.
See the Thread.start() javadoc for more information.
There are other ways to accomplish what you are trying to do. For example, you could use new Threads that continue the work that was done in the Thread that has finished execution. You may also want to investigate the java.util.concurrent package.
From another post...
You could use ThreadPoolExecutor, which would allow you to pass in tasks and let the service assign a thread to a task. When the task is finished, the thread goes idle until it gets the next task.
So, you don't restart a thread, but you would redo/resume a task.