2013-07-13 43 views
8

この投稿は、私がスイングに依存してブロックするためにスレッドとブールフラグを表示することを指示する学校の宿題に関連しています。マルチスレッドが正しく動作しない

私のアプリケーションは、それぞれがスレッドを含む「ジョブ」オブジェクトの束を作成します。それぞれの仕事はクリーチャーに属しています。クリーチャーは複数の仕事を持つことができますが、任意の瞬間に1つしか実行できません。

スレッドは、 "killFlag"と "goFlag"という名前で実行する必要があるかどうかを判断するために2つのブール型フラグを使用します。それは、それが所属するクリーチャーを「ターゲット」として指定する。各ターゲットには、別のジョブでビジーであるかどうかを示すブーリアン「isWorking」があります。

これは、各ジョブを実行するスレッドです:

public void run() { 
    long time = System.currentTimeMillis(); 
    long startTime = time; 
    long stopTime = time + 1000 * (long)(jobTime); 
    double duration = stopTime - time; 



    synchronized (this.target) { 
     while (this.target.isWorking) { 
      status = 'w'; 
      showStatus(); // hmmmmmmmm 
      try { 
       this.target.wait(); 
      } catch (InterruptedException e) { 
      } 
     } 

     this.target.isWorking = true; 
    } 

    while (time < stopTime && !killFlag) { 
     try { 
      TimeUnit.MILLISECONDS.sleep(100); 
     } catch (InterruptedException e) { 
     } 

     if (goFlag) { 
      status = 'p'; 
      showStatus(); 
      time += 100; 
      this.showProgress.setValue((int)(((time - startTime)/duration) * 100)); 
     } else { 
      status = 'r'; 
      showStatus(); 
     } 
    }//End While loop here 

     showProgress.setValue(100); 
     status = 'c'; 
     showStatus(); 
     synchronized (target) { 
      target.isWorking = false; 
      target.notifyAll(); 

    } 
} 

最初に私はそれがIllegalMonitorStateExceptionを投げているので、それはtarget.notifyAll()だと思ったが、私はスレッドをそれをコメントアウトしたときにオブジェクトが構築されますが、私は見たときになりますそれらのGUIの80%は、私からの介入なしで完全に表示され、他の20%は、そのクリーチャーがビジー状態であると述べています。

私はこれがkillフラグをあまりにも早くポップするからだと思っていましたが、私がそれを下に移動したり削除したりしても症状は依然として残ります。私は現時点で導入されており、ここにはプログラマーはいません。あなたが提供できるアドバイスは、世界を意味します。

私がスレッドとやりとりするために使用する方法は、私が十分な情報を提供していることを確認するためです。以下のメソッドは、スレッドが実行されているかどうかによって変更されるボタンで動作します。

これは私を殺しています。私はこれを6時間解決するために掘り下げてきました。

MadProgrammerさんのコメント "target.notifyAll()" に基づいて私のコードを調整した後、編集は

固定されています。今、問題は、ボタンが数秒間の間に状態間でランダムに点滅しても、すべてのスレッドがディスプレイ上に完全に表示されるように見えます。

編集

編集の多くは、コメントの下

に応じて、以下に含ま私はなどkillFlag、goFlagは、定義されたジョブクラスを定義する方法です。以下は

class Job extends Item implements SearchableByName, Runnable { 
int           index; 
String          name; 
int           creature; 
double          jobTime; 
Creature         target; 
boolean          goFlag = false; 
boolean          killFlag = false; 
char          status; 
JButton          startJob; 
JButton          stopJob; 
JProgressBar        showProgress; 
JPanel          p1; 

ブールisWorkingがどこにあるクリーチャー(ターゲット)が定義されている場所です。

class Creature extends Entity implements SearchableByName, SearchableByType, Runnable { 
int          party; 
int          empathy; 
int          fear; 
int          carryCapacity; 
Float         age; 
Float         height; 
Float         weight; 
boolean         isWorking = false; 

そして、ここでコメントへの応答では、私がスレッドを表示していますかの写真です: enter image description here

+5

新しいコードでは、より高いレベルの並行性の抽象化を使用する必要があります。スレッドではなく、タスクとエグゼキュータの観点からプロジェクトを定義する必要があります。 wait、notify、およびnotifyAllを正しく使用することは特に困難です。あなたのスレッドを調整する方法を議論する方法は、おそらくCountDownLatchを使うべきです。独自のセマフォーフラグは、少なくともあなたがそれらに加えた更新が他のスレッドに見えることを保証していないので、少なくともvolatileで宣言する必要があります。 – scottb

+5

GUIの表示がありますが、フレームワークの識別はありません。スイングを使用している場合は、[スレッドの同時実行性](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)を参照して、単一スレッドのルールに違反していることを強くお勧めします。 – MadProgrammer

+1

target.notifyAllはsynchronizedブロック内から実行する必要があります。notifyAllはモニターロックが動作するようにする必要があります。 – MadProgrammer

答えて

2

まだいくつかのコードが不足しているので、私はまずいくつかの前提を列挙します。いずれかが保持されない場合は、以下の私の答えが間違っている可能性があります。

  1. あなたが指定したrun()メソッドは、Jobクラスの内部にあります。
  2. 「キャンセル」ボタン、あなたが参照するには、stopJobJButton

あなたが実行スルー1日以降に再起動の同じJobインスタンスを再利用することを意図している場合は、あなたの基本的な問題は、あなたのrun()ということですメソッドは終了します。 !killFlagをチェックするwhileループがありますが、そのループが終了すると(つまり、ジョブがキャンセルされた後にはkillFlag == true)、それが最初に戻って次のgoFlag == true状態が再び実行されるのを待つものはありません。 (また、あなたのactionPerformed()方法でstopJob節がgoFlagで何かをする必要があるかどうかを検討してください。)一方

、あなたが再起動し、ジョブを表すために、新しいJobインスタンスを作成しようとしている場合、あなたの避難所に」それを行うコードを示しています。

私は、上記の私の診断で、あなたが自分自身で物事を理解するのを助けるために、少し漠然としています - それは学ぶための最善の方法です。 :)詳細が必要な場合は、コメントにLMKだけを提供してみてください。

+0

ありがとう!あなたは本当に私がする必要があることについていくつかの光を当てました!私はボタンを囲む問題の大半を修正しました。私は、キャンセルボタンを押して実行ボタンでスレッドを開始すると、スレッドを終了させることになると思います。私は今それを行う安全な方法を探しています。もう一度ありがとう、私は十分にあなたに感謝できませんでした! –

関連する問題