HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Decrease CPU usage in while loop

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
whileloopusagecpudecrease

Problem

I've a application which runs with two threads. The main thread runs in one infinity-while-loop:

while (true) {
   try {
      ArrayList infoList = zabbixHandler.APIRequest();
      handleInfo.handleInformation(infoList);
      Thread.sleep(5000);
   }
}


The second thread, which uses more than 50% of my CPU, must be able to stop and run again, which I asked already with this question on Stack Overflow.

The solution works perfectly, but as I already said, it uses >50% of the CPU. Here are the two loops of the solution:

```
private volatile boolean finished = true;
public void run() {
Process p;

while (true) {
// loop until the thread is finished
while (!finished) {
try {

// let every lamp shine...
p = Runtime.getRuntime().exec(onCommand + "-green");
p.waitFor();

// ... for 0.5 seconds ...
Thread.sleep(500);

// ... then turn it off again ...
p = Runtime.getRuntime().exec(offCommand + "-green");
p.waitFor();
// ... and let the next lamp shine
p = Runtime.getRuntime().exec(onCommand + "-yellow");
p.waitFor();

Thread.sleep(500);

p = Runtime.getRuntime().exec(offCommand + "-yellow");
p.waitFor();
p = Runtime.getRuntime().exec(onCommand + "-red");
p.waitFor();

Thread.sleep(500);

p = Runtime.getRuntime().exec(offCommand + "-red");
p.waitFor();
p = Runtime.getRuntime().exec(onCommand + "-blue");
p.waitFor();

Thread.sleep(500);

p = Runtime.getRuntime().exec(offCommand + "-blue");
p.waitFor();

} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStac

Solution

don't use a busy wait but instead use a wait condition (here using the built-in monitor in Object):

public void run() {
   while(true){
      while(!finished){
         // do stuff
      }
      try{
          synchronized(this){
              while(finished)
                   wait();//wait until notify gets called in startThread
          }
      }catch(InterruptedException e){}
   }

}

public synchronized void startThread() {
   finished = false;
   notify();//wake up the wait
}


I note that finished should remain volatile.

I put the wait() in the synchronized block in a while loop to avoid the race where the thread has just tested the first while condition and is about to enter the synchronized block but startThread() then gets called; putting finished back to false and the thread waiting anyway. This can lead to the thread blocking while waiting on a notify() that never happens.

To help any more I need to see what exactly happens inside that while loop.

Code Snippets

public void run() {
   while(true){
      while(!finished){
         // do stuff
      }
      try{
          synchronized(this){
              while(finished)
                   wait();//wait until notify gets called in startThread
          }
      }catch(InterruptedException e){}
   }

}

public synchronized void startThread() {
   finished = false;
   notify();//wake up the wait
}

Context

StackExchange Code Review Q#39152, answer score: 9

Revisions (0)

No revisions yet.