2012-10-28 69 views
1

意外輸出I具有如下:2個線程修改共享的BlockingQueue

public class ProducerConsumer { 

    private BlockingQueue<Integer> q; 
    private Random rnd; 
    private boolean run; 

    public ProducerConsumer(){ 
    rnd = new Random(); 
    q = new ArrayBlockingQueue<>(10); 
    run = true; 
    } 

    // high leve - with ArrayBlockingQueue 

    public void QProducer() throws InterruptedException{  
    int i; 
    while(run){ 
     i = rnd.nextInt(100); 

     q.put(i); 
     System.out.println(i +" Added. Size is: "+ q.size()); 
    } 
    } 

    public void QConsumer() throws InterruptedException{ 
    int i; 
    while(run){ 
     Thread.sleep(100); 
     if (rnd.nextInt(10) == 0) { 

      i = q.take(); 
      System.out.println(i + " Taken. Size is: "+ q.size()); 
     } 
    } 
    } 

public void changeRun(){ 
    run = false; 
}  
} 

public static void main(String[] args) throws InterruptedException { 

    // Producer Consumer 

    final ProducerConsumer pc = new ProducerConsumer(); 

    Thread t1 = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      try { 
       pc.QProducer(); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Threading.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    }); 

    Thread t2 = new Thread(new Runnable() { 

     @Override 
     public void run() { 
      try { 
       pc.QConsumer(); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(Threading.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    }); 

    t1.start(); 
    t2.start(); 

    Scanner scn = new Scanner(System.in); 

    scn.nextLine(); 
    pc.changeRun(); 

    t1.join(); 
    t2.join(); 

} 

Ouptput:

20 Added. Size is: 1 
8 Added. Size is: 2 
71 Added. Size is: 3 
72 Added. Size is: 4 
61 Added. Size is: 5 
97 Added. Size is: 6 
6 Added. Size is: 7 
64 Added. Size is: 8 
58 Added. Size is: 9 
27 Added. Size is: 10 
20 Taken. Size is: 10 * 
93 Added. Size is: 10 
8 Taken. Size is: 9 
95 Added. Size is: 10 
71 Taken. Size is: 10 * 
70 Added. Size is: 10 
72 Taken. Size is: 10 * 
85 Added. Size is: 10 
61 Taken. Size is: 9 
43 Added. Size is: 10 
64 Added. Size is: 10 ** 
... 

不知如何能有被採取數字,並且尺寸保持不變(*), 以及隊列填滿(**)後值如何增加。 AFAIU,BlockingQueue被同步化,並且在隊列爲空時等待要添加的值,如果已滿則刪除值。 預先感謝您。

回答

1

之後的put()println/size()以及它之後的take()println/size()可以因爲多線程而被交織。因此,size()返回的值可能會在打印時過期。例如。

1a. Add (size = 10) 
    1b. Print size 10 
2a. Take (size = 9) 
3a. Add (size = 10) 
    2b. Print size 10 
    3b. Print size 10 
+0

由於我懷疑(但不能批准) – InterruptedException

0

由於您沒有​​區塊,因此您的put操作不是原子的,而是size查詢。正如你所見證的那樣,在這兩者之間可以發生其他線程的任何數量的動作—。