0

I'm very new into Threads and I'm facing following problem when using a thread in my code.

On a button click I'm starting a thread which runs a specific task, and this task is running in the background of the system. I am using a while loop inside the thread to check if a volatile bool is changed by another button click to stop the whole process. The problem is I have to add an empty loop else it looks like the thread stops itself and does not check for the while condition anymore. I assume this is very inefficient and wastes a lot of ressources.

I'm adding a shorted version of the code to make it less unreadable.

Any idea why this happens and how I could improve the overall efficiency of my code?

public void onClick(View view) {

    new Thread(new Runnable() {

           public void run() {
            //execute my task

           while(!stopThread) {
           // Without this empty loop the thread stops after a while

  }
           while(stopThread) { // stopThread is a volatile bool changed by another button click
           //Finish the task
           break;
    }
  }
  }).start();
  }
  • 3
    I guess that `stopThread` has the initial value of `false`, which causes your 2nd loop not to be executed and the threads terminates. Instead of using a loop you could share some lock `object` between both buttons, and use `wait` and `notify` instead. Chech [`this tutorial`](https://www.baeldung.com/java-wait-notify). – second Sep 29 '19 at 16:38
  • @second I suggest making an Answer of your Comment so this Question can be marked resolved. – Basil Bourque Sep 29 '19 at 16:48
  • I guess my fault was thinking that the thread would let the while condition loop infinitely but seems like it terminates after checking it once. I will definitely check out the link, thanks a lot. – Hyung Duc Da Sep 29 '19 at 16:50
  • @second Could you help me out with the wait() and notify(). I see I need a synchronized object because else I'm crashing when calling thread.notify() from another button click. I just don't exactly know how to implement that into my existing code. I'm very new into android and could need a little help. – Hyung Duc Da Sep 29 '19 at 17:44
  • 1
    I have added a simplified example to my answer. – second Sep 29 '19 at 17:59

1 Answers1

2

I guess that stopThread has the initial value of false, which causes your 2nd loop not to be executed and the threads terminates.

Instead of using a loop you could share some lock object between both buttons, and use wait and notify instead. Check this tutorial.

A possible Implementation could look like this:

Both buttons need access to these two variables:

Object lock = new Object();
volatile boolean stopThread = false;


The onClick method of the first button:

public void onClick(View view) {

    new Thread(new Runnable() {

        public void run() {

            // execute my task

            synchronized (lock) {
                // stopThread is a volatile boolean changed by another button click
                while (stopThread == false) {
                    lock.wait();
                }
            }

            // Finish the task
        }
    }).start();
}


The onClick method of the second button:

public void onClick(View view) {

    new Thread(new Runnable() {

        public void run() {

            synchronized (lock) {

                stopThread = true;
                lock.notify();
            }
        }
    }).start();
}

You will want to keep the boolean flag around to handle spurious wakeups. If the condition is fullfilled you continue with your code, else you go back to wait for the notification.

Note that the example does not deal with any interrupts that may happen.


You might want to use AsyncTask.execute instead of starting Threads on your own.
Check this answer.

second
  • 4,069
  • 2
  • 9
  • 24
  • One questions got in my mind, doesn't the while( stopThread == false) eat up alot of ressources incase the background process runs for a longer time untill I press the second button? – Hyung Duc Da Sep 29 '19 at 18:18
  • 1
    The loop condition should cost you almost nothing. Normally it will only be checked twice (for entering the loop and for leaving). For the resource consumption of the waiting thread itself, check [`this`](https://stackoverflow.com/q/38235700/11514534) answer. – second Sep 29 '19 at 20:12