2012-11-16 143 views
0

所以我一直在試圖編寫一個java程序,涉及線程。這基本上是一個線程詢問共享內存資源(下面的代碼中的單元類)是否允許移動的問題。我將向您展示線程中的代碼示例。從cell類中提到的三種方法是同步方法,但是它們不實現等待或通知。線程管理

public void run() { 
    try{ 
     while(true){ 
      Random r = new Random(); 
      Thread.sleep(r.nextInt(1000)); 
      //asks the class cell permission to move if the cell is free. 
      if(cell.asksAccess(xi, yi, xf, yf)){ 
       cell.releaseCell(xi, yi); //release the previous cell 
       move(); // move the object 
       cell.blockCell(xi, yi); // blocks the cell where the object is now staying. 
       setChanged(); 
       notifyObservers(); 
      } 
     } 
    } catch (InterruptedException e) { 
    } 
} 

private void move() { 
    int dx = xf - xi; 
    int dy = yf - yi; 

    xi += (int) Math.signum(dx); 
    yi += (int) Math.signum(dy); 
} 

就像我之前說過的,調用的所有單元類方法都是同步的。我的問題是,這不符合我的預期,當我做了一個sysout調試時,它顯示線程並不總是前進,有時甚至會回到他們開始時的位置,我不明白爲什麼因爲移動方法總是告訴他們前進並永不回頭。這是與單元類同步的問題嗎?或者它是移動方法?任何幫助將不勝感激。

+0

我懷疑你是不是同步數據,以便所有線程都在讀/寫單元的本地varions或者其他的東西。很難告訴所示的代碼。 – Gray

+0

您應該將'Random'移到while外面,並在Thread.sleep(...);'周圍移動InterruptedException。哦,並且總是至少打印'InterruptedException'並重新中斷該線程。 – Gray

+0

線程被授予訪問單元的權限是100%,然後在執行if塊中的任何步驟之前產生控制權。你需要同步整個'外部'邏輯塊。 – Perception

回答

0

首先,讓我們考慮一下move的方法。假設:

  • xixfyiyf變量是Runnable的實例變量,並
  • 有訪問或更新它們沒有其他(回調)方法,

然後我們可以得出結論,那些變量是「線程受限」的,不需要同步。

那麼問題在哪裏?嗯,我想它是在這裏:

if (cell.asksAccess(xi, yi, xf, yf)) { 
    cell.releaseCell(xi, yi); //release the previous cell 
    move(); // move the object 
    cell.blockCell(xi, yi); // blocks the cell where the object is now staying. 
    setChanged(); 
    notifyObservers(); 
} 

我可以看到兩個問題:

  • 我覺得你說askCellblockCellreleaseCellcell對象上同步。但問題在於序列「問,封鎖,放行」需要是原子的。
  • 您的代碼似乎正在釋放單元格(?)xi, yi ...然後再次阻止它。評論似乎暗示你應該打電話給cell.blockCell(xf, yf)

...什麼是採取該序列的同步護理的最好方法?

沒有看到相關的代碼,很難說最好的方法是什麼。但是其中一個這樣做的方法是在cell對象上撥打一個電話......然後處理move和通知;例如是這樣的:

if (cell.checkAndMove(xi, yi, xf, yf)) { 
    move(); // move the object 
    setChanged(); 
    notifyObservers(); 
} 

其中checkAndMoveCell類定義爲:

public synchronized boolean checkAndMove(int xi, int yi, int xf, int yf) { 
    boolean ok = this.asksAccess(xi, yi, xf, yf); 
    if (ok) { 
     this.releaseCell(xi, yi); 
     this.blockCell(xi, yi); 
    } 
    return ok; 
} 
+0

我想我明白了。還有一件事,關注該序列同步的最佳方法是什麼?謝謝。關於第二個問題,由於在更新xi和yi之間的move()方法,xi,yi在釋放單元格和塊單元格中不同。 – Nmas

+0

這是一個很好的解決問題的方法,現在我想我可以從中解決問題。我現在可以明白之前有什麼不對,並希望不會犯同樣的錯誤。非常感謝你的時間,這真的很有幫助。 – Nmas

0

private void move()方法應該同步。

+0

但void move()在線程中,沒有其他線程會請求訪問此移動,爲什麼如果我同步移動方法會有所幫助? – Nmas