2017-03-16 1 views
0

나는 약 10 개 Thread의 호출 시나리오를 가지고 있고, Notifier 클래스 I 특정 Thread의 통지 할 통지까지 Thread이있는 각 기다릴, 내가 무엇을하고 있는가하는 것은 내가 keyThread ID와 Thread 인스턴스와 함께 HashMap을 사용하고있다 값. 나중에 Notifier 나는 Thread 인스턴스를 제공하는지도 map.get(threadId)을 가로 지르면서이를 알리려고하고 있습니다. 그리고 그걸 알리려고 노력하고 있지만, IllegalmonitorException을 던지고 있습니다. YES : 나는 당신의 질문에 대한 HashMap 또는 WaiterNotifier 클래스 모두에서 Thread ..스레드 객체를 hashmap 내에 저장할 수 있습니까?

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

안녕하세요. 크롤러 알리미 클래스에서 알리겠습니다. 코드를 수정했습니다.보세요 !!!!! – Tirumalesh

+0

Thread 객체에서 동기화를 피해야하며'thread.wait()'또는'thread.notify()'를 호출하면 안됩니다. 그 이유는'Thread' 클래스는 자체적으로'wait()'와'notify()'를 사용하기 때문입니다. 가장 좋은 방법은 _any_ 라이브러리 객체에서 결코 동기화하지 않는 것입니다. 대신에,'private final Object lock = new Object();'를 만들 수 있고 대신에 그것을 동기화 할 수 있습니다. –

답변

0

대답인지 여부를 동기화 할 것을 의심의 여지 데. thread는 객체이기 (위해) 때문에, HashMap에 포함 할 수가 있습니다.

어쨌든, @ T.J.Crowder는 당신이 통보를 사용하는 방식이 틀렸다고 말했습니다. 이 스레드는 (map.get(entry.getKey()).notify();)의 잠금이없는 개체를 통해 을 호출하기 때문에 발생합니다. 코드가 우리를 같이 대신에, 스레드의 잠금 장치가있는 객체 Runner (instance.notify())의 notify를 호출한다 : 모든 instance.wait();

최초! 당신이 블록을 syncrhonize해야 wait 방법 등으로 스레드를 차단하는 오브젝트 instance : 기다리는 것 같은데 중지하고 스레드를 계속하고 syncrhonized 블록을 떠날 방법 개체의 notifyRunner 전화,

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

을 그리고, 이 같은 : 에게 대구를 : considere있는 것이

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

그러나, 현재의 코드는, 예를 들어, 여러 섹션을 다시 작성해야하기 때문에이 팁을 구현하기 너무 어렵다 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 –

관련 문제