2

すべてが実行されるか、特定の条件が満たされるまで、連続して実行する必要のある一連のプロシージャがあります。条件が満たされるまで実行する必要がある基本的なコードは次のとおりです。

public boolean search()
{
    robot.go();

    robot.spin();

    //etc - around 8 more similar commands (each takes around 2 seconds)
    return false; //didn't find what it was looking for
}

これまでのところ、私がやりたいことをやろうと思った唯一の方法はこれです:

public boolean search()
{
    robot.go(false);
    while(robot.isMoving())
    {
        if(thingFound())
        {
            robot.stop()
            return true;
        }
        Thread.yield();
    }

    robot.spin(false);
    while(robot.isMoving())
    {
        if(thingFound())
        {
            robot.stop()
            return true;
        }
        Thread.yield();
    }


    //etc - around 8 more similar commands
    return false; //didn't find what it was looking for
}

とへのfalseパラメーターは、それらがすぐに戻る必要があることを示し、条件をチェックできるようにしますgo()spin()ただし、同じコードブロックを10回繰り返す必要があるため、このアプローチはかなり非効率的です。これは、例外または同時スレッドでより効率的に達成できますか?

4

4 に答える 4

3

なぜ使用しているのかわからないThread.yield()-あなたが言及しなかった他のスレッドが実行されていますか?または多分私は問題を読み間違えました。

コマンドパターンがここで機能する可能性があると思います。メソッドとのRobotCommandインターフェースexecute、およびコマンドタイプごとの実装RobotCommand(go、spinなど)があります。次に、のをとして構築しRobotAlgorithm、リストを繰り返し処理するメソッドを作成し、それぞれを呼び出して、それぞれの後に結果を確認することができます。ListRobotCommandexecuteRobotAlgorithmexecuteRobotCommandthingFound()

編集-ああ、私はそれを理解したと思います。goロボットの状態をspin変えるスレッド、またはそのようなものを開始しますか?

編集2-あなたのコメントに応えて、ここでの問題は、ロボットが探しているものを見つけたらすぐに戻ることができる必要があるということのようですが、、、goなどのspinコマンドは今これを行いません、そしてあなたはその間、新しいコマンドを実行し続ける機能が必要です。Listしたがって、ここで行う可能性があるのは、2つのスレッドです。1つは、1つずつ実行する「エグゼキュータ」スレッドとRobotCommand、スリープとポーリングを繰り返す「ウォッチャー」スレッドです(チェックthingFound())。真の場合thingFound()は、ロボットとエグゼキュータスレッドを停止できます。または、エグゼキュータがthingFound()真になる前に最後に到達した場合は、そのように通知できます(必要な場合)。

于 2010-01-09T19:03:03.500 に答える
2

明らかに、whileループは独自の関数にパッケージ化できます。

private boolean isFound()
{
    while (robot.isMoving())
    {
        if (thingFound())
        {
            robot.stop()
            return true;
        }
        Thread.yield();
    }
    return false;
}

public boolean search()
{
    robot.go(false);
    if (isFound()) return true;

    robot.spin(false);
    if (isFound()) return true;   

    //etc - around 8 more similar commands
    return false; //didn't find what it was looking for
}

(条件が2行に分割されていてもかまいません。おそらく、実稼働コードでそれを行います。)

私よりも優れたJavaプログラマーは、「プロシージャ」(Cプログラミングの観点からは関数へのポインタ)を渡すことができるかどうかを教えてくれます。 できると思いますが、構文と規則がわかりません。証拠はあなたができないということ のようです(とにかく、2004年頃)。

于 2010-01-09T19:14:32.070 に答える
0

ロボットは、Conditionオブジェクトを使用して、サブタスクが完了したか、新しい状態に入ったことをコントローラーに通知できます。

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/Condition.html

興味深いことに、そこにある環境では、より柔軟な条件の代わりに、notify()wait()を使用して通知することができます。コントローラは、ロボットがnotify()で彼を解放することを決定するまでwait()することができます。

于 2010-01-09T19:09:40.643 に答える
0

Jonathan Lefflerの回答に基づく:コマンドへの ポインター
としてRunnableを使用できます

private final Runnable going = new Runnable() {
    @Override
    public void run() {
        robot.go(false);
    }
});

private final Runnable spinning = new Runnable {
    @Override
    public void run() {
        robot.spin(false);
    }
});

// other commands 


private boolean isFoundAfter(Runnable command)
{
    command.run();
    while (robot.isMoving())
    {
        if (thingFound())
        {
            robot.stop()
            return true;
        }
        Thread.yield();
    }
    return false;
}

public boolean search()
{
    if (isFoundAfter(going)) return true;

    if (isFoundAfter(spinning)) return true;   

    //etc - around 8 more similar commands
    return false; //didn't find what it was looking for
}


必要に応じて、さらに1つのステップで、コマンドを配列またはリストに配置し、スクリプトとして実行します。

...

private boolean executeSearch(Runnable... commands)
{
    for (Runnable cmd : commands) {
        if (isFoundAfter(cmd)) return true;
    }
    return false; //didn't find what it was looking for
}

public boolean search() {
    return executeSearch(going, spinning /* around 8 more similar commands */);
}
于 2010-01-09T23:53:03.693 に答える