2017-09-22 15 views
0

私はJavaスレッドコーディングのテストを受けていますが、基本的な問題がいくつかあります。通知でロックを解除できません

私の待ち時間はまだロックされている理由を私は理解することはできません後でも、私の通知:

public class Mymain { 

    public static void main(String[] args) { 

     for(int i=0;i<100;i++){ 
      new ThreadClass(i).start();  
     } 
    } 
} 

public class ThreadClass extends Thread { 
    static boolean ok = false; 
    int id; 

    public ThreadClass(int i) { 
     id = i; 
    } 

    public void run() { 
     System.out.println("Thread start " + id); 
     Last.toDo(id); 
     if (id == 5) 
      try { 
       waiting(); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     if (id != 5) 
      awaking(); 

     System.out.println("thread end " + id); 
    } 

    private synchronized void awaking() { 
     // TODO Auto-generated method stub 
     if (ok) { 
      System.out.println("i'm " + id + " and i'm Awaking 5"); 
      ok = false; 
      notify(); 
      System.out.println("I did the notify and i'm " + id); 
     } 
    } 

    private synchronized void waiting() throws InterruptedException { 
     System.out.println("Sleeping"); 
     ok = true; 
     wait(); 
     System.out.println("Awake 5"); 
    } 
} 

Result

はその後、それがループを開始するか、それが行く:ここ

あなたは私のコードを見つけることができますデッドロックではわかりません。id = 5のスレッドを停止し、次のスレッドはid = 5 ..を再起動する必要がありますが、スレッド5は通知後も起きません。

あなたが見ることができるように、2つのスレッドがスレッド5を起こそうとしていて、スレッド5が開始以来常に待ち続けている^^

+0

あなたの出力が何であり、どのようなものであるべきか私達に教えてください。 –

+0

あなたは簡単な分析のためにフォーマットすることができるようにそれをあなたの質問に入れることができますか? –

+0

@WarrenDew完了^^ – JustMe

答えて

-1

ルック:

  1. あなただけnotify()、あなたはthisに通知しますすることはできません。そして、あなたはただwait()できません、あなたは永遠に待つでしょう。これらの関数をオブジェクトに対して使用する必要があるので、Integerオブジェクトを追加しました(ちょうどあなたには正しいオブジェクトを選択する必要があります)。
  2. あなたは​​とstatic synchronizedの間で理解しています。クイック検索は完璧な答えにつながります。
  3. なぜ機能waiting()が同期されていますか?スレッド番号5だけがそれを呼び出します。
  4. Object.notify()/Object.wait()を呼び出すときは、オブジェクトの上に同期ブロックを宣言する必要があります。ここで

は、いくつかのコードです:

public class Threads { 
    public static void main(String[] args) { 
     Integer intObject = new Integer(0); 
     for(int i=0;i<100;i++){ 

      new ThreadClass(i, intObject).start();  
     } 
    } 
} 
class ThreadClass extends Thread { 
    static boolean ok = false; 
    int id; 
    Integer intObject; 
    public ThreadClass(int i, Integer intObject) { 
     id = i; 
     this.intObject = intObject; 
    } 

    public void run() { 
     System.out.println("Thread start " + id); 
     //Last.toDo(id); 
     if (id == 5) 
      waiting(); 
     else 
      awaking(this); 

     System.out.println("thread end " + id); 
    } 

    private static synchronized void awaking(ThreadClass t) { 
     if(ok) { 
      System.out.println("i'm " + t.id + " and i'm Awaking 5"); 
      ok = false; 
      synchronized (t.intObject) { 
        t.intObject.notify(); 
       } 
      System.out.println("I did the notify and i'm " + t.id); 
     } 
    } 
    private void waiting(){ 
     System.out.println("Sleeping"); 
     ok = true; 
     synchronized (intObject) { 
      try { 
       intObject.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
     System.out.println("Awake 5"); 
    } 
} 
+0

答えのためのTyは非常に明確です^^今私はそれを得ました^^ – JustMe

+1

これは、ロックする整数は恐ろしい考えです。これは、サンプルを動作させるために必要なようではありません。 –

+0

ええ、私はそれを書いただけで、オブジェクトと同期して作業する方法をデモンストレーションします。 – Yinon

0

問題はあなたがnotify()あなたはwait()を呼び出しました。特に、スレッド5は自分自身でwait()を呼び出していますが、スレッド8はスレッド5ではなくnotify()を呼び出しています。その結果、スレッド5は決して通知されません。

また、ok変数をvolatileにする必要があります。これは、あるスレッドがスレッドを設定したときに他のスレッドがその変更を確認できるようにするためです。この特定のケースでは問題は発生していませんが、それ以外の場合には問題が発生する可能性があります。

+0

私はあまりにも(最初の3行)この端に来たが、私はスレッド5に通知するためにどのようにすればよいか分からない。それはおそらく何か基本的な私は無視している.. ^^ Tyのヘルプ:D – JustMe

+0

"ok"変数を揮発性Object変数に置き換える方法があります。 trueではなくnonnullをチェックすると、スレッド5はオブジェクトを作成してそれを待ちます。他のスレッドは、それがあれば通知します。 –

+0

ええ、私はすべてのためにタイを得ました^^ – JustMe

0

私は私の待ち時間はまだ私には通知した後もロックされている理由を理解することはできません。

待ちをして、同じオブジェクトインスタンスが使用されている場合、作業を通知します。例えば、あなたが持っている場合:

String x1 = "..."; 
String x2 = "..."; 

とスレッド#1の処理が行われます。

synchronized (x1) { x1.wait(); } 

とスレッド#2は、その後行われますので、

synchronized (x2) { x2.wait(); } 

が続いてスレッド#1はまだ待ってます通知はx2のみでした。あなたの例では、メソッド同期を使用しているので、id 5のスレッドはThreadClassという独自のインスタンスを待機しています。そして、他のスレッドがawaking()を呼び出すと、そのインスタンスに対してThreadClassの通知を呼び出しています。スレッド#5が他のスレッドの通知を見たい場合は、ロックオブジェクトを共有する必要があります。

は多分のようなもの:私はあなたのコードにいくつかの変更を行いました

final Object lock = new Object(); 
for (int id = 0; id < 100; id++){ 
     new ThreadClass(id, lock).start();  
} 
... 
public class ThreadClass extends Thread { 
    private final Object lock; 
    ... 
    public ThreadClass(int id, Object lock) { 
     this.id = id; 
     this.lock = lock; 
    } 
    ... 
    private void awaking() { 
     ... 
     synchronized (lock) { 
      lock.notify(); 
     } 
     ... 
    } 
    private void waiting() throws InterruptedException { 
     ... 
     synchronized (lock) { 
      lock.wait(); 
     } 
     ... 
    } 
} 
+0

答えのためのTyは非常に明確です^^今私はそれを得ました^^ – JustMe

0

あなたはのnotifyAll()メソッドを使用していないのはなぜ? notify()を呼び出すと、ステータスがからrunnableに変更されるスレッドが1つだけ変更されますが、複数のスレッドや他のスレッドが同時に行内に待機している場合がありますこの通知を受け取ることはありません。私の意見では、notifyAllを使用することが望ましいです。

+0

そう思わない^^私は他のメンバーから提案されたように解決しました^^ – JustMe

+0

この投稿は正確に質問に答えるものではありません。スレッドが同じロックを使用しない場合は、どのメソッドを呼び出すかは関係ありません。 –

関連する問題