1

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.

Kasra
  • 3,045
  • 3
  • 17
  • 34

4 Answers4

5

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();
MikeHelland
  • 1,151
  • 1
  • 7
  • 17
2

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)

Community
  • 1
  • 1
Andres
  • 6,080
  • 13
  • 60
  • 110
0

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

Community
  • 1
  • 1
zapl
  • 63,179
  • 10
  • 123
  • 154
0

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 :

  1. 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.

  2. 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.

  3. Inter-Thread or Inter-Process communication is quite common requirement.

Anirudh
  • 389
  • 1
  • 7
  • The OP wants to run his thread multiple times. So if that is the case, as per the [documentation - Threading Rules](http://developer.android.com/reference/android/os/AsyncTask.html) an AsyncTask can be run only once: `The task can be executed only once (an exception will be thrown if a second execution is attempted.)` – anddev84 Jan 26 '14 at 05:45
  • @anddev84, AsyncTask internally user Thread Pool. He needs to create new instance of AsyncTask everytime and it will take care of rest. I have already mentioned this Key Concepts. – Anirudh Jan 26 '14 at 05:48
  • Fair enough. I guess I missed that statement the first time I read your answer. – anddev84 Jan 26 '14 at 05:52
  • Thanks for your response... Just a quick question, is Async Task UI-Dependent? I mean what if during the calculation I rotate the screen? Does it make the processing stop? If so, is there a quick fix to avoid the Async Task gets interrupted? – Kasra Jan 26 '14 at 08:35
  • @Kasra, http://stackoverflow.com/questions/7128670/best-practice-asynctask-during-orientation-change – Anirudh Jan 28 '14 at 06:09