2012-11-16 105 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