2017-03-16 6 views
0

私はいくつかの10 Thread秒を呼び出すシナリオを持ち、かつ各ThreadNotifierクラスは、私は特定のThread Sを通知したい通知まで待たなければならない、私がやっていることは、私はkeyThreadインスタンスなどとしてThread IDでHashMapを使用していますです値。後でNotifier私はThreadを与えるmap.get(threadId)の地図を横切って通知しようとしていますが、私はそのことを通知しようとしていますが、それはIllegalmonitorExceptionを投げています。 YES:私はあなたの質問のためのHashMapまたはWaiterNotifierクラスの両方でThread ..スレッドオブジェクトをハッシュマップに格納することは可能ですか?

package com.cgi.sample.jms.requestor; 

import java.util.HashMap; 
import java.util.Map; 
import java.util.UUID; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class RequestorApplication { 
    private final Object lock = new Object(); 
    public static String correlationId; 

    public static String getCorrelationId() { 
     correlationId = UUID.randomUUID().toString(); 
     return correlationId; 
    } 

    public static void main(String args[]) throws Exception { 

     Map<Long, Thread> map = new HashMap<Long, Thread>(); 

     ExecutorService executor = Executors.newFixedThreadPool(5); 
     for (int i = 0; i < 2; i++) { 

      Waiter waiter = new Waiter(map); 

      executor.execute(waiter); 

      Notifier notifier = new Notifier(map); 
      executor.execute(notifier); 
     } 

     System.out.println("All the threads are started"); 
    } 
} 

class Waiter implements Runnable { 

    Map<Long, Thread> map; 
    ExecutorService executor = Executors.newFixedThreadPool(5); 

    public Waiter(Map<Long, Thread> map) { 
     this.map = map; 
    } 

    public void run() { 

     ExecutorService executor = Executors.newFixedThreadPool(5); 

     for (int i = 0; i < 2; i++) { 

      Runner instance = new Runner(); 

      System.out.println("Executing thread " + " with " + Thread.currentThread().getName()); 

      long threadId = Thread.currentThread().getId(); 

      String threadname = Thread.currentThread().getName(); 

      executor.execute(instance); 

      synchronized (map) { 

       map.put(threadId, Thread.currentThread()); 

       try { 
        instance.wait(); 
        System.out.println(threadname + " Thread entered into waiting state!!!"); 
        // Thread.currentThread().wait(); 
        System.out.println(threadname + " Thread woke up from wait!!!!!"); 

       } catch (InterruptedException e) { 

        e.printStackTrace(); 
       } 
      } 
     } 

    } 

} 

class Notifier implements Runnable { 

    Map<Long, Thread> map; 

    public Notifier(Map<Long, Thread> map) 

    { 
     this.map = map; 
    } 

    public synchronized void run() { 

     synchronized (map) { 

      for (Map.Entry<Long, Thread> entry : map.entrySet()) { 

       System.out.println("stored threads in map are--->" + map.get(entry.getKey())); 

       map.get(entry.getKey()).notify(); 

      } 

     } 
    } 
} 

class Runner implements Runnable { 

    public void run() { 
     System.out.println("runner invoked"); 

    } 
} 
+0

*「スレッドオブジェクトをハッシュマップに保存することはできますか?」「はい、それはあなたの問題ではありません。あなたの問題は、オブジェクトのモニターの所有者ではないスレッドのオブジェクトに対して 'notify'のドキュメント(' http://docs.oracle.com/javase/8/docs/api ')として 'notify'を呼び出すことです/java/lang/Object.html#notify--)があなたに伝えます。 'notify'呼び出しを表示していないので、私たちはあなたにそれを手伝うことはできません。 –

+0

Hi.Crowder Notifierクラスから通知しています。コードを修正しました。 – Tirumalesh

+0

Threadオブジェクトの同期は避け、 'thread.wait()'や 'thread.notify()'を呼ばないでください。なぜなら、 'Thread'クラスはそれ自身の目的のために' wait() 'と' notify() 'を利用するからです。経験則としては、どのライブラリオブジェクトでも決して同期させないことです。代わりに、 'private final Object lock = new Object();'を作成し、その代わりに同期させることができます。 –

答えて

0

答えがあるかどうかを同期させるためにどのような疑問持っています。スレッドはオブジェクトなので、HashMapに格納することができます。

他の方法では、@ T.J.Crowderはあなたに通知しました。あなたは通知を使用する方法が間違っています。これは、スレッド(map.get(entry.getKey()).notify();)のロックを持たないオブジェクトに対して、を呼び出すためです。代わりにあなたのコードは、私たちに示して、スレッドのロックを持つオブジェクトRunnerinstance.notify())、のnotifyを呼び出す必要があります:すべてのinstance.wait();

初!あなたがブロックをsyncrhonizeしなければならないwait方法、等とのスレッドブロックしますオブジェクトinstance:waitting停止し、スレッドを継続しsyncrhonizedブロックを残すための方法オブジェクトのnotifyRunnerを呼び出し、

synchronized(instance){ 
    try{ 
    instance.wait() 
    }catch(...) 
    { 
    //Do Something else 
    } 
} 

をそして、

map.get(entry.getKey()).getRunnerInstance().notify();

しかし、あなたは例えば、いくつかのセクションを書き換える必要がありますので、あなたの現在のコードは、このヒントを実装するのは難しいですし、それをconsidere:このような何かタラeスレッドのブロックのためにforループのコンテキストに居るオブジェクトを使用している場所

for (int i = 0; i < 2; i++) { 

    Runner instance = new Runner(); 
    //... 
    synchronized (map) { 

      map.put(threadId, Thread.currentThread()); 

      try { 
       instance.wait(); //You are blocking over a instance declared into the For Loop. 
      }catch(..){ 
       //.. 
      }; 
    } 

} 
+0

マップにあるスレッドインスタンスのRunnerInstanceを取得する方法を教えてください。 – Tirumalesh

+0

このリンクを確認してください:http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example –

関連する問題