0

だから私はスレッドを含むJavaプログラムを書こうとしてきました。これは基本的に、スレッドが共有メモリリソース(以下のコードのセルクラス)に移動の許可を求める場合に問題になります。スレッド内のコードの例を示します。セルクラスの前述の3つのメソッドは同期メソッドですが、待機または通知を実装していません。

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を実行すると、スレッドが常に前進しているとは限らず、スレッドが最初の場所に戻ってしまうこともあり、その理由がわかりません。なぜなら、moveメソッドは常に前進し、決して後退しないように指示するからです。これはセルクラスとの同期の問題ですか?それとも移動方法ですか?どんな助けでも大歓迎です。

4

2 に答える 2

0

プライベートvoidmove()メソッドを同期する必要があります。

于 2012-11-16T23:31:06.460 に答える
0

まず、move方法を考えてみましょう。仮定して:

  • xi、、および変数は、、およびのインスタンスxf変数です。yiyfRunnable
  • それらにアクセスまたは更新する他の(コールバック)メソッドはありません。

そうすれば、これらの変数は「スレッド制限」されており、同期は必要ないと結論付けることができます。

では、どこに問題があるのでしょうか。さて、私はそれがここにあると思います:

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();
}

私は2つの問題を見ることができます:

  • あなたはそう言ったと思いますaskCellblockCellそしてオブジェクトでreleaseCell同期しcellます。しかし、問題は、「尋ねる、ブロックする、解放する」というシーケンスがアトミックである必要があるということです。
  • あなたのコードはxi, yi...でセル(?)を解放し、それを再びブロックしているようです。cell.blockCell(xf, yf)コメントは、代わりに電話する必要があることを示唆しているようです。

...そのシーケンスの同期を処理するための最良の方法は何ですか?

関連するコードを見ずに、最善の方法が何であるかを言うのは難しいです。しかし、それを行う1つのcell方法は、オブジェクトに対して1回の呼び出しを行い、move後で通知を処理することです。たとえば、次のようなものです。

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

ここで、クラスでcheckAndMoveは次のように定義されています。Cell

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;
}
于 2012-11-17T00:38:52.933 に答える