0

JConsoleスタックトレースによると、プロデューサーとコンシューマーのスレッドセットがありますが、プロデューサーは、ではないコード行でスタックしています。.put()

class Producer implements Runnable {
    private final BlockingQueue<CopyOnWriteArrayList<Creature>> queue;
    private World myWorld;

    Producer(BlockingQueue<CopyOnWriteArrayList<Creature>> q, World myWorld) {
        queue = q;
        this.myWorld = myWorld;
    }

    public void run() {
        int nextTick = myWorld.myApp.getTick(); //'tick' is the current frame our main loop is on.      
        while (true) {
            if (myWorld.myApp.getTick() >= nextTick) { //if our world has updated to the next frame…
                nextTick = myWorld.myApp.getTick() + 1; //increment the next frame to wait for

                try {
                    for (int i = 0; i < myWorld.getCellController()
                            .getColumns(); i++) {
                        for (int j = 0; j < myWorld.getCellController()
                                .getRows(); j++) {

                            queue.put(myWorld.getCellController().Cells.get(i)
                                    .get(j));
                        }
                    }
                } catch (InterruptedException ex) {
                    System.out.println("INT! ******************************");
                } catch (NullPointerException ex) {
                    System.out.println("NULL! ******************************");
                } catch (ClassCastException ex) {
                    System.out.println("CAST! ******************************");
                } catch (IllegalArgumentException ex) {
                    System.out.println("ARG! ******************************");
                }
            }
        }
    }
}

スタックトレースによるとwhile(true)、ループを進むことなく、ライン上にとどまるだけです。

Stack trace:
Name: Producer
State: RUNNABLE
Total blocked: 0  Total waited: 196,958

Stack trace: 
concurrency.Producer.run(Setup.java:25)
java.lang.Thread.run(Thread.java:680)

25行目がそのwhile(true) {行です。

4

1 に答える 1

0

getTick()スレッドセーフですか?つまり、ティック値に到達する途中に、同期されたキーワード、何らかの形式のロック、揮発性の読み取り、またはアトミック変数がありますか?そうでない場合、スレッドはティックカウンターに加えられた同時変更を認識しない可能性があります。中断してデバッグすると、これらの変更が強制的に表示される場合があります。

さらに、プロデューサーは成功を待つのではなくqueue.put()、アプリケーションが次のティックに進むのを待つ必要があるようです。myWorld.myApp.getTick()ブロッキングですか?そうでない場合、次の場合を除いて、コードは無限にループします。

  • ティックを同時に変更する他のスレッドがあります
  • あなたのスレッドは中断され、別の目覚めたスレッドがティックを変更します

条件の変更(別名ポーリング/スピン待機)をチェックするために無限ループを使用することは、変更の可能性がある場合にのみ意味があります。

waitForTick(int tick)ブロッキングを実装し、オブジェクトで安全に公開することをお勧めしますmyWorld.myApp。スレッドセーフコレクションとは別に、さまざまなスレッドを同期するために使用できるセマフォ、バリアなどの他の同時コンポーネントがあります。

于 2013-02-17T05:39:00.877 に答える