2013-02-17 40 views
0

根據JConsole堆棧跟蹤,我有一個生產者 - 消費者線程集,但生產者陷入不是.put()的一行代碼中。生產者線程卡住但未阻塞

class Producer implements Runnable { 
    private final BlockingQueue<CopyOnWriteArrayList<Creature>> queue; 
    private World myWorld; 

    Producer(BlockingQueue<CopyOnWriteArrayList<Creature>> q, World myWorld) { 
     queue = q; 
     this.myWorld = myWorld; 
    } 

    public void run() { 
     int nextTick = myWorld.myApp.getTick(); //'tick' is the current frame our main loop is on.  
     while (true) { 
      if (myWorld.myApp.getTick() >= nextTick) { //if our world has updated to the next frame… 
       nextTick = myWorld.myApp.getTick() + 1; //increment the next frame to wait for 

       try { 
        for (int i = 0; i < myWorld.getCellController() 
          .getColumns(); i++) { 
         for (int j = 0; j < myWorld.getCellController() 
           .getRows(); j++) { 

          queue.put(myWorld.getCellController().Cells.get(i) 
            .get(j)); 
         } 
        } 
       } catch (InterruptedException ex) { 
        System.out.println("INT! ******************************"); 
       } catch (NullPointerException ex) { 
        System.out.println("NULL! ******************************"); 
       } catch (ClassCastException ex) { 
        System.out.println("CAST! ******************************"); 
       } catch (IllegalArgumentException ex) { 
        System.out.println("ARG! ******************************"); 
       } 
      } 
     } 
    } 
} 

根據堆棧跟蹤,它只是停留在while(true)線,而無需通過循環前進,即使它應該。

Stack trace: 
Name: Producer 
State: RUNNABLE 
Total blocked: 0 Total waited: 196,958 

Stack trace: 
concurrency.Producer.run(Setup.java:25) 
java.lang.Thread.run(Thread.java:680) 

25行是while(true) {行。

+0

你正在使用哪個阻塞隊列的實現? – Perception 2013-02-17 05:02:27

+0

我已經嘗試了'ArrayBlockingQueue'和'LinkedBlockingQueue',它與兩個掛起。 – honkbert 2013-02-17 05:06:04

+0

請將(JConsole)堆棧跟蹤添加到您的問題中。 – Perception 2013-02-17 05:11:41

回答

0

getTick()線程安全嗎?即是否有一個同步關鍵字,某種形式的鎖,易失性讀取或Atomic變量在去往刻度值的路上?如果不是,你的線程可能看不到對tick計數器作出的同時更改。破解和調試可能會強制這些更改顯示。

此外,看起來你的製作人不應該等待成功queue.put(),而是讓應用程序前進到下一個打勾。是myWorld.myApp.getTick()阻塞?如果沒有,你的代碼將只是無限循環,除非:

  • 還有其他線程修改蜱同時
  • 你的線程被掛起,而另一個語驚醒夢中人線程修改蜱

使用一個無限循環檢查條件的變化(aka輪詢/自旋等待)只有在發生變化的情況下才有意義。

我建議在對象myWorld.myApp中實施阻止並安全地公開waitForTick(int tick)。除了線程安全集合之外,還有其他可用於同步不同線程的併發組件,如信號量,障礙等。

+0

'getTick()'線程安全嗎?不,它只是在每次單獨的主線程(遊戲控制器)循環迭代時返回包含+1的int變量。主線程是修改「int」節拍的唯一線程。每當我調試和中斷時,getTick的值就會增加到足以滿足if語句的程度。生產者線程始終在該條件語句上循環,所以我不明白爲什麼它最終不會看到變化。 – honkbert 2013-02-17 05:46:18

+0

使'getTick()'返回'volatile'變量成功了。 – honkbert 2013-02-17 07:55:49