4

私は2つのスレッドを実行しています。1 つは 、もう 1 つはTimeStepThreadですCarThread。はCarThread500 ミリ秒ごとに実行されます。私が与えたTimeStepThreadどんな間隔でも走ります。これで、500 ミリ秒ごとCarThreadに、道路上の車の位置の動きが更新されます。ただし、が呼び出されるたびに、TimeStepThreadその車の位置の値を取得したいと考えています。たとえば、500 ミリ秒ごとに更新される車が 1 台ありますが、2 秒ごとにその車の位置にラベルを設定したいと考えています。

私のクラスは次のように設定されています:

  1. Simulationクラスには
  2. TimeStepThreadCarThread

私のSimulation(またはフレームではなく)では、車の位置の値をタイムステップ間隔ごとに更新したいと考えています。したがって、2000 ミリ秒ごとに、Simulation クラスで何かを更新する/何かを返す必要があります。

これを行う方法がわかりません。私のスレッドは の中にあるので、 からメソッドをSimulation実際に呼び出すことはできません 。言うまでもなく、少し面倒です。リスナー、おそらく?Simulationrun()


編集:タイムステップスレッドですでに車にアクセスできます。これは問題ではありません。車を保持するコンテナ クラスを使用しています。両方のスレッドがアクセスでき、CarThread更新も可能です。私の問題は、TimeStepThread が呼び出されるたびに更新された文字列を持つ Simulation クラス、または TimeStepThread が呼び出されるたびに更新されるフレーム ラベルに関するものです。

4

4 に答える 4

1

2 つのスレッド内の 2 つのクラスは、どちらも車のリストにアクセスする必要があります。

この場合、車は car クラスのインスタンスです。

タイム ステップ スレッドには、その作業を実装するクラスがあります。(車の位置を読んでいます。)

車のスレッドには、その作業を実装するクラスがあります。(これは位置を更新しています。)

各実行タイプのクラスは、車のオブジェクトにアクセスして、位置変更情報で更新するか、何かを読み取ります。たとえば、位置にアクセスする車のクラス (または後述の車のコンテナ) のインスタンス メソッドを使用する必要がsynchronizeあるため、さまざまなスレッドが互いに影響しません。

ここで実装する類似の方法が 2 つあります。

1) 車を作成するたびに、それを 2 つの作業クラスのそれぞれに渡します。彼らはそれぞれ、すべての車の独自の内部リストを保持しています。車を手放す場合は、両方に伝えなければなりません。

2) 最初に、2 つの作業クラスのそれぞれに車のコンテナー クラスへの参照を与えます。単なるリストかもしれませんが、並行リストです。たぶんカスタムクラス。車を作成するときは、車のコンテナ クラスを (追加して) 伝えます。車をなくしたときも、それを伝えます。

Simulation クラスに関しては、車の位置が変化したときに通知する必要があります。ここでも 2 つの方法がありますが、それらは似ています。

どちらの場合も、更新を行っているクラスにシミュレーション クラスのインスタンスを渡す必要があります。シミュレーション クラスにはメソッドがupdateCar()あり、更新が完了すると更新クラスが呼び出すとします。

1) バージョン 1 - シミュレーション クラス インスタンスへの呼び出しは、何かが変更されたことを伝えるだけです。シミュレーション クラスのコードは、何が変更されたかを特定して対処するか、すべてを更新するだけです。

2) バージョン 2 - シミュレーション クラス インスタンスの呼び出しには、変更されたすべての車のリストが含まれます。シミュレーション クラスは、何が変更されたかを検索する必要がなく、変更されたものだけを更新できます。

注意が必要なのは、その更新メソッドへの呼び出しが更新スレッドで発生していることを覚えておく必要があることです。たとえば、Swing を使用して画面上のテキストを更新する場合は、SwingWorker を使用してイベント スレッドで更新を取得する必要があります。

その作業を安全なスレッドに移動できない場合は、すべての適切なものが並行しているか同期していることを確認して、それらが互いに踏み込まないようにする必要があります。

于 2013-05-20T15:30:39.550 に答える
0

リストやその他のデータ構造は必要ないと思います。これは次のように簡単です。

public class Car

    private volatile int position;


    public int getPosition() {
        return position;
    }

    public void setPosition(int position) {
        this.position = position;
    }

}

public class CarThread extends Thread {

    private final Car car;

    public CarThread(Car car) {
        this.car = car;
    }

    @Override
    public void run() {
        Thread.sleep(500);
        car.setPosition(//whatever)
    }
}

public class TimeStepThread extends Thread {

    private final Car car;

    public CarThread(Car car) {
        this.car = car;
    }

    @Override
    public void run() {
        Thread.sleep(2000);
        int position = car.getPosition()

        // do stuff
    }
}

Car の同じインスタンスをすべてに渡すようにしてください。

この回答は、すべての位置変更をキューに入れる必要はなく、最新の位置のみが重要であることも前提としています。これを使用して、地図などに車の位置を描画する場合は、適正。

編集

すべてをまとめるには、次のようにしてみてください。

public class TimeStepThread extends Thread {

    private final Car car;
    private final JFrame frame;


    public TimeStepThread(Car car, JFrame frame) {
        this.car = car;
        this.frame = frame;
    }

    @Override
    public void run() {
        while(true) {
            Thread.sleep(2000);
            EventQueue.invokeLater(new Runnable() {

                @Override
                public void run() {
                    frame.setTitle(Integer.toString(car.getPosition()));
                }
            }
        }
    }
}
于 2013-05-20T15:41:40.420 に答える
0

クラスに aConcurrentLinkedQueueを入れることができます-スレッドは位置の更新をキューに送信します。次に、スレッドはすべての位置の更新を処理し (キューが空になるまで)、ラベルを配置します。SimulationCarTimesteppoll

BlockingQueueまたは、クラスにを入れて、キューからSimulation継続的にスレッドを作成takeし、位置情報を更新することもできます。

このようにして、コードを変更することなく、必要に応じて車を追加できSimulationます。すべての車が更新を同じキューに送信します。

于 2013-05-20T15:28:06.883 に答える
0

あなたの車の進歩のためのリスナーが最良のアプローチだと思います。あなたは次のようなことができます

public interface CarProgressListener {
    void positionChanged(Position currentPosition);
}

次に、TimestepThreadこのインターフェイスを実装して に登録しCarThreadます。

public CarThread extends Thread {
     private final Collection<CarProgressListener> progressListeners = new LinkedList<>();
     // other stuff
     public void addListener(CarProgressListener listener) {
         this.progressListeners.add(listener);
     }
}

public TimestepThread extends Thread implements CarProgressListener {
     private Position lastHeardCarPosition;

     // remenber to initiate this thread with the first car position.

     @Override
     public void positionChanged(Position currentPosition) {
         this.lastHeardCarPosition = currentPosition;
     }
}

だから、あなたのSimulationクラスでは、次のようなものが必要になります

...
Position initialPosition = // get it from somewhere.
CarThread car = new CarThread(initialPosition);
TimestepThread timestepThread = new TimestepThread(initialPosition);

car.addListener(timestepThread);
...    
于 2013-05-20T15:28:41.950 に答える