Consider this class, AnimationThread:
class AnimationThread implements Runnable {
public void pause() {
doAnimation = false;
}
public void doStart(){
doAnimation = true;
}
#Override
public void run() {
// TODO Auto-generated method stub
if (doAnimation) {
//my code
}
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
}
}
}
Now I am starting this thread in onCreate of an activity (just showing rough code):
AnimationThread animRunnable = new AnimationThread();
animationThread = new Thread(animRunnable);
animationThread.start();
But run() is getting called just once (I traced a log to confirm that). I just want to know that when I started the thread why run() is not getting called repeatedly with 500 sleep. It is just called once.
That is how it is supposed to be.
A Thread runs by executing its run method (just once). After that it is considered done/dead/finished/completed.
If you want to loop, you have to do it yourself (inside of the run method), or use some ExecutorService to call the Runnable repeatedly.
Of course the run() method will be executed once. If you want to repeat the statements inside the run method then you have to use loop. Take a look at TimerTask - will runs a task at a specified time or repeatedly.
EDIT:
Android - Controlling a task with Timer and TimerTask?
Timer task schedule
Related
i am writing code from online to create a chat application. After trouble shooting my program to find out why it is not working I have discovered that the code inside my run method here is not being reached. here is the snippet of code
public void listen()
{
listen = new Thread("Listen") {
public void run()
{
writeMessage("Working in here");
while (true) {
String message = client.receive();
if (message.startsWith("/c/")) {
client.setID(Integer.parseInt(message.substring(3, message.length())));
writeMessage("Successfully connected to server" + client.getID());
}
}
}
};
}
It is reaching the listen method itself, because if i use the write message command before i declare the thread, it prints out the message for me, any idea from looking at this why it will not enter any further?
Thanks
Calling start() on your Thread would do it:
public void listen()
{
listen = new Thread("Listen") {
public void run()
{
writeMessage("Working in here");
while (true) {
String message = client.receive();
if (message.startsWith("/c/")) {
client.setID(Integer.parseInt(message.substring(3, message.length())));
writeMessage("Successfully connected to server" + client.getID());
}
}
}
};
listen.start(); // <-- Add this line
}
Also, you typically don't want to extend Thread (which you are doing here with an anonymous class). Usually you'll want to create a Runnable and pass that to Thread's constructor instead:
Runnable r = new Runnable() {
#Override
public void run()
{
// Do some work here
}
};
Thread listen = new Thread(r, "Listen");
listen.start();
Or even better, use an Executor, there aren't many good reasons to create your own Thread objects.
Certainly working with appropriate Execotor or even better ExecutorService is more appropriate way of working with threads today. Read about it here. But if you insist on working the old way then you need to invoke start() method of your thread. Methods start() and run() do the same thing, only run() execute your thread sequentially i.e. in the same thread where you invoked it and start() actually starts a new thread where your code is executed which is what you wanted in the first place
I need to call the same thread multiple times in my app. Using my original code, the first time is can be executed just fine. But the second time it crashes - I then learned that each thread shall only be executed not more than one time.
My original piece of code:
View.OnClickListener myClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
mythread.start();
}
};
Thread mythread = new Thread(){
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
So as I said, it crashes if I try to run it for the second time. So I tried modifying it like:
View.OnClickListener myClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
test();
}
};
private void test(){
Thread mythread = new Thread(){
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
mythread.start();
}
It works very good; but my question is that whether this is the correct way to do this action or there is a more optimal way to do this?
Also, is it an acceptable thing to call a thread from insider of another thread? (like the way I put stuff on UI Thread inside the new thread of mine)
EDIT:
This is just an example. For my actual code I have heavy math-based simulation to be done which takes 10sec to be done. Based on the results that will be shown to the user , they may want to change their input parameters and let the simulation run again. This will happen several times.
In addition to the other good answers about using AsyncTask or runOnUiThread(), you could define a private member as a Runnable, like this:
private Runnable mytask = new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Running...");
}
});
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
demoBt.setText("Finished...");
}
});
}
};
Then, whenever you want to run it, do
new Thread(mytask).start();
There is nothing bad with that but I think a better way would be using AsyncTask. It is exactly designed for this cases.
You can use AsyncTask multiple times just creating a new one like this new MyAsyncTask().execute(""); (source from here)
Also, is it an acceptable thing to call a thread from insider of another thread? (like the way I put stuff on UI Thread inside the new thread of mine)
runOnUiThread exists solely for that purpose. But there are usually much better ways (e.g. AsyncTask) so using this method is probably a bad idea.
my question is that whether this is the correct way to do this action or there is a more optimal way to do this?
You should not use a thread just to schedule future tasks. They are useful to execute something in parallel to the main thread but add lots of potential errors (try rotating the screen between it prints running..finished, could crash)
I would use a CountDownTimer in your case.
Or a Handler, examples e.g. here: Schedule task in android
From the provided code I assume that you want to perform an UI operation before and after your long mathematical computation. In such as #Andres suggested, AsyncTask is your best buy. It provides method onPreExecute, onPostExecute which runs on UI thread, and thus no need for explicitly calling runOnUiThread.
Key concepts :
You can't start an already started thread. This will return in an IllegalStateException. If you need to perform same task again, you should create a new instance.
If you find yourself creating several instances of a thread (even AsyncTask), since you need to run same task again and again, I would suggest you to use Thread Pool or simple Java Executor Service. Create a singleThread or may be pool and post your runnable onto executorService and it will take care of the rest.
Inter-Thread or Inter-Process communication is quite common requirement.
I have a class "TestRunnable" which overrides run method by implementing Runnable.
Running overridden run method, as follow :
TestRunnable nr = new TestRunnable();
Thread t = new Thread(nr);
t.setName("Fred");
t.start();
What if i directly call t.run();
What happen if we don't call t.start(); ?
The run method is just another method. If you call it directly, then it will execute not in another thread, but in the current thread.
Here's my test TestRunnable:
class TestRunnable implements Runnable
{
public void run()
{
System.out.println("TestRunnable in " + Thread.currentThread().getName());
}
}
Output if only start is called:
TestRunnable in Fred
Output if only run is called:
TestRunnable in main
If start isn't called, then the Thread created will never run. The main thread will finish and the Thread will be garbage collected.
Output if neither is called: (nothing)
If you call start method then a separate thread will be allocated to execute the run method, means you achieve multi threading . But when you call run method directly then it becomes a normal method and main method itself will execute the run method , means no multi threading.
If run() method is called directly instead of start() method in Java code, run() method will be treated as a normal overridden method of the thread class (or runnable interface). This run method will be executed within the context of the current thread, not in a new thread.
Example
Let’s create a class and spawn two threads and cause some delay in the execution if they are real threads then there will be context switching – while one thread is not executing another thread will execute. When the start method is not called no new threads are created thus there won’t be any context switching and the execution will be sequential.
public class MyThreadClass extends Thread{
#Override
public void run(){
System.out.println("In run method " + Thread.currentThread().getName());
for(int i = 0; i < 5 ; i++){
System.out.println("i - " + i);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
MyThreadClass mc1 = new MyThreadClass(“MyThread1”);
MyThreadClass mc2 = new MyThreadClass();
mc1.run();
mc2.run();
}
}
I've created a timer class and am testing it with junit4. The timer is notifies another class of the time which then activates a method. While testing I am unable to check what values are sent to the observer because the compiler gets stuck in the always loop used for the timer. Here's the test and the start code for the timer.
public void testSimpleTimerAsThread() throws InterruptedException
{
SimpleTimer st = new SimpleTimer(1000);
st.start();
Thread.sleep(250); // So we are 1/4th a second different
for (int x=0;x<5;x++)
{
assertEquals(x, st.getRound()); // assumes round starts at
Thread.sleep(1000); // wait for the next time change
}
}
public void start()
{
while (flag)
{
timeChanged();
try
{
// Sleep for var seconds.
Thread.sleep(1000);
}
catch (InterruptedException e)
{
}
}
}
Thanks for the help.
In the SimpleTimer class you should be overriding the run() method, not start().
Assuming SimpleTimer extends Thread, you have overridden the method in Thread that actually creates and launches the thread, so no new thread is being created and your thread code is being executed in the main thread when you invoke start(), which is why it hangs.
I have some code which executes a download in a separate thread, created so that the JFrame GUI will continue to update during the download. But, the purpose is completely defeated when I use Thread.join(), as it causes the GUI to stop updating. I need a way to wait for the thread to finish and still update the GUI.
You can have the task that does the download also fire an event to the GUI.
For example:
Runnable task = new Runnable() {
public void run() {
// do your download
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// call some method to tell the GUI that the download finished.
}
});
}
};
and then to run it, either use an Executor (preferred method) or a raw thread:
executor.execute(task);
or
new Thread(task).start();
As pointed out in the comments, you'd generally use a SwingWorker to do this kind of thing but you can also do the manual approach outlined above.
SwingWorker provides a doInBackground method where you would stick your download logic in, a done method where you would stick in code to notify the GUI that the download finished and a get method to get the result of doInBackground (if there was one).
E.g.,
class Downloader extends SwingWorker<Object, Object> {
#Override
public Object doInBackground() {
return doDownload();
}
#Override
protected void done() {
try {
frame.downloadDone(get());
} catch (Exception ignore) {
}
}
}
(new Downloader()).execute();