2013-07-03 94 views
0

我知道如何做到這一點,但我想知道爲什麼這個代碼運行,因爲我會做,**沒有任何指出的錯誤**,而如果我刪除Thread.sleep( 100);行來自兩個while循環,程序進入無限循環狀態?空while循環的線程問題

import java.util.Random; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.Random; 
import java.util.Random; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
interface Buffer 
{ 
    // place int value into Buffer 
    public void set(int value) throws InterruptedException; 

    // obtain int value from Buffer 
    public int get() throws InterruptedException; 
} // end interface Buffer 


public class javaapplication32 
{ 
    public static void main(String[] args) 
    { 
     // create new thread pool with two threads 
     ExecutorService application = Executors.newCachedThreadPool(); 

     // create CircularBuffer to store ints 
     CircularBuffer sharedLocation = new CircularBuffer(); 

     // display the initial state of the CircularBuffer 
     sharedLocation.displayState("Initial State"); 

     // execute the Producer and Consumer tasks 
     application.execute(new Producer(sharedLocation)); 
     application.execute(new Consumer(sharedLocation)); 

     application.shutdown(); 
    } // end main 
} 
// Consumer.java 
// Consumer's run method loops ten times reading a value from buffer. 


class Consumer implements Runnable 
{ 
    private final static Random generator = new Random(); 
    private final Buffer sharedLocation; // reference to shared object 

    // constructor 
    public Consumer(Buffer shared) 
    { 
     sharedLocation = shared; 
    } // end Consumer constructor 

    // read sharedLocation's value 10 times and sum the values 
    public void run() 
    { 
     int sum = 0; 

     for (int count = 1; count <= 10; count++) 
     { 
     // sleep 0 to 3 seconds, read value from buffer and add to sum 
     try 
     { 
      Thread.sleep(generator.nextInt(3000));  
      sum += sharedLocation.get(); 
     } // end try 
     // if lines 26 or 27 get interrupted, print stack trace 
     catch (InterruptedException exception) 
     { 
      exception.printStackTrace(); 
     } // end catch 
     } // end for 

     System.out.printf("\n%s %d\n%s\n", 
     "Consumer read values totaling", sum, "Terminating Consumer"); 
    } // end method run 
} // end class Consumer 

class Producer implements Runnable 
{ 
    private final static Random generator = new Random(); 
    private final Buffer sharedLocation; // reference to shared object 

    // constructor 
    public Producer(Buffer shared) 
    { 
     sharedLocation = shared; 
    } // end Producer constructor 

    // store values from 1 to 10 in sharedLocation 
    public void run() 
    { 
     int sum = 0; 

     for (int count = 1; count <= 10; count++) 
     { 
     try // sleep 0 to 3 seconds, then place value in Buffer 
     { 
      Thread.sleep(generator.nextInt(3000)); // sleep thread 
      sharedLocation.set(count); // set value in buffer 
      sum += count; // increment sum of values 
     } // end try 
     // if lines 25 or 26 get interrupted, print stack trace 
     catch (InterruptedException exception) 
     { 
      exception.printStackTrace(); 
     } // end catch 
     } // end for 

     System.out.println( 
     "Producer done producing\nTerminating Producer"); 
    } // end method run 
} // end class Producer 

class CircularBuffer implements Buffer 
{ 
    private final int[] buffer = { -1, -1, -1 }; // shared buffer 

    private int occupiedCells = 0; // count number of buffers used 
    private int writeIndex = 0; // index of next element to write to 
    private int readIndex = 0; // index of next element to read 

    // place value into buffer 
    public void set(int value) throws InterruptedException 
    { 
     // wait until buffer has space avaialble, then write value; 
     // while no empty locations, place thread in waiting state 
     while ( occupiedCells == buffer.length) 
     { 
     Thread.sleep(100); 
     } // end while 

     buffer[ writeIndex ] = value; // set new buffer value 

     // update circular write index 
     writeIndex = (writeIndex + 1) % buffer.length; 

     ++occupiedCells; // one more buffer cell is full 
     displayState("Producer writes " + value); 
    // notifyAll(); // notify threads waiting to read from buffer 
    } // end method set 

    // return value from buffer 
    public int get() throws InterruptedException 
    { 
     // wait until buffer has data, then read value; 
     // while no data to read, place thread in waiting state 
     while (occupiedCells == 0) 
     { 
     **Thread.sleep(100);** 
     } // end while 

     int readValue = buffer[ readIndex ]; // read value from buffer 

     // update circular read index 
     readIndex = (readIndex + 1) % buffer.length; 

     --occupiedCells; // one fewer buffer cells are occupied 
     displayState("Consumer reads " + readValue); 
    // notifyAll(); // notify threads waiting to write to buffer 

     return readValue; 
    } // end method get 

    // display current operation and buffer state 
    public void displayState(String operation) 
    { 
     // output operation and number of occupied buffer cells 
     System.out.printf("%s%s%d)\n%s", operation, 
     " (buffer cells occupied: ", occupiedCells, "buffer cells: "); 

     for (int value : buffer) 
     System.out.printf(" %2d ", value); // output values in buffer 

     System.out.print("\n    "); 

     for (int i = 0; i < buffer.length; i++) 
     System.out.print("---- "); 

     System.out.print("\n    "); 

     for (int i = 0; i < buffer.length; i++) 
     { 
     if (i == writeIndex && i == readIndex) 
      System.out.print(" WR"); // both write and read index 
     else if (i == writeIndex) 
      System.out.print(" W "); // just write index 
     else if (i == readIndex) 
      System.out.print(" R "); // just read index 
     else 
      System.out.print("  "); // neither index 
     } // end for 

     System.out.println("\n"); 
    } // end method displayState 
} 

我的問題不在於如何正確地做到這一點,但它是

  • 如果我上面我得到我想要的東西運行此代碼,試試就知道它是如何工作
  • 但如果我刪除Thread.sleep(100);同時形成循環,代碼不運行,因爲我運行它Thread.sleep(100);前一種情況下爲
+2

你的代碼是在一個有限循環中的任何一種方式,它只是處理器只是檢查條件每秒十次而不是數千次,而不是睡着了。 – meiamsome

+1

無關,但仍然 - http://www.oracle.com/technetwork/java/javase/documentation/codeconvtoc-136057.html –

+1

您選擇的方法非常糟糕,太糟糕了!爲什麼你在一次又一次檢查一個變量,你需要[同步](http://arashmd.blogspot.com/2013/06/java-threading.html#synctr)線程互相 – 2013-07-03 20:48:44

回答

2

Thread.sleep s用於減少不必要的CPU使用量。在沒有睡眠的單核心繫統上,可能會導致CPU時間的其他線程捱餓,因此脫離自旋鎖可能需要很長時間。無論如何,look into using wait() and notify()不是實現你自己的自旋鎖。

+2

+1你在時間和質量上擊敗了我:D –

+0

也可以建議使用併發包:http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary .html – Jyro117

+0

@ Jyro117看起來他已經是某種程度了。 :) – Zong

0

我不相信它是無限的,但它將朝着這個方向發展。查看使用的處理器容量。只要兩個線程在相同的進程中運行,共享相同的處理器核心。我敢打賭,檢查將獲得所有資源...