2

次のようなコードがあります。

Algorithm a = null;  
while(a == null)  
{  
    a = grid.getAlgorithm();  
}  

私のGridクラスのgetAlgorithm()は、ユーザーがいくつかのオプションから何を選択したかに応じて、Algorithmのサブタイプを返します。

私の問題は、アルゴリズムが選択された後でも、ループが終了しないことです。ただし、System.out.println( "Got here");を配置するだけの場合は、これは難しいことではありません。getAlgorithm()を呼び出した後、プログラムは完全に正常に実行され、ループは意図したとおりに終了します。

私の質問は、なぜその魔法の印刷ステートメントを追加するとループが突然終了するのですか?

さらに、この問題は私が新しいラップトップを使い始めたときに最初に発生しました。それが関連しているとは思えませんが、言及する価値があると思いました。

編集:問題のプログラムはマルチスレッドではありません。getAlgorithm()のコードは次のとおりです。

public Algorithm getAlgorithm ()  
{  
    return algorithm;  
}

ここで、アルゴリズムは最初はnullですが、ユーザー入力によって値が変更されます。

4

5 に答える 5

2

この問題は、grid.getAlgorithm の実行方法に対処する必要があると思います。メソッドの実行に関連するコストがほとんどない場合、メソッドが null を返し続ける限り、while ループは非常に速く循環します。これは、ビジー待機と呼ばれることがよくあります。

新しいラップトップで、古いコンピューターでは発生しなかった飢餓の問題が発生しているようです。理由を言うのは難しいですが、上記のリンクを見ると、ウィキペディアの記事はビジーな待機が予測できない動作をすることを示しています。おそらく、古いコンピューターは、新しいラップトップよりもユーザー IO を適切に処理できます。とにかく、新しいラップトップでは、そのループはユーザー IO を処理しているものからリソースを奪っているため、ループを壊す原因となるプロセスが不足しています。

于 2011-03-13T04:32:55.457 に答える
1

アクティブなポーリングを行っています。これは悪い習慣です。少なくともポーリングスレッドをスリープ状態にする必要があります(Thread.sleepを使用)。printlnはいくつかのioを実行するので、おそらくそれを実行します。アプリがマルチスレッド化されていない場合、まったく機能しない可能性があります。

于 2011-03-13T03:51:22.527 に答える
1

このループが GUI でのユーザー入力を待機することである場合は、問題があります。悪い、悪い考えであり、Thread.sleep()追加されたとしても、私は決してお勧めしません. 代わりに、問題のコンポーネントにイベント リスナーを登録し、コンテンツが変更されたときにのみ検証コードを起動することをお勧めします。

アプリケーションがマルチスレッド化されている場合は特に、なんらかの形のデッドロックに到達しているため、プログラムがロックアップしている可能性が高くなります。この問題を解決してハッキングするよりも、アプリケーションのこの部分の仕組みを再設計することを真剣に検討したいと思います。

于 2011-03-13T03:58:22.593 に答える
0

getAlgorithm() を確認する必要があります。メソッドに問題があるはずです。

于 2011-03-13T04:08:32.240 に答える
0

次の 2 つのシナリオがあります。

  1. あなたのコードは、実際にはマルチスレッド化を意図していません。この場合、何らかのユーザー入力をループに挿入する必要があります。それ以外の場合は、Algorithm a = grid.getAlgorithm(); のままにしておくこともできます。無限ループを防ぎます。
  2. コードがマルチスレッド化されている場合、何らかの「可視性」の問題があります。Atomicity, Visibility and Ordering に移動するか、 Java Concurrency in Practiceを読んで、可視性について詳しく学んでください。基本的に、スレッド間の何らかの同期がなければ、ループしているスレッドは、JVM が実行する可能性のある最適化のために値が変更されたことに気付かない可能性があることを意味します。

このコードの実行方法に関するコンテキストについては言及していません。コンソール ベースのアプリケーションで、「メイン」関数から開始した場合、マルチスレッドが存在するかどうかがわかります。マルチスレッドがないと言っているので、これは当てはまらないと思います。もう 1 つのオプションは、これが Swing アプリケーションであるということです。その場合は、Multithreaded Swing Applicationsを読む必要があります。これは、swing と同様のケースが当てはまる Web アプリケーションである可能性があります。

いずれの場合でも、いつでもアプリケーションをデバッグして、どのスレッドが「algorithm」変数に書き込みを行っているかを確認し、次にどのスレッドがそこから読み取りを行っているかを確認できます。

これがお役に立てば幸いです。いずれにせよ、質問にもう少し文脈を与えると、より多くの助けが得られるかもしれません. 特に、「Java の奇妙な問題、while ループの終了」などの興味深いタイトルの質問については。

于 2011-03-13T21:17:13.220 に答える