title: is it possible to store thread objects inside hashmap?
body: <p>I have scenario where I invoke some 10 <code>Thread</code>s, and each <code>Thread</code> has to wait till <code>Notifier</code> class notifies I want to notify specific <code>Thread</code>s, what I am doing is i am using <code>HashMap</code> with <code>Thread</code> id as <code>key</code> and the <code>Thread</code> instance as value. Later in the <code>Notifier</code> i am trying to notify it by traversing the map <code>map.get(threadId)</code> which gives <code>Thread</code> instance and I'm trying to call notify on that but it is throwing <code>IllegalmonitorException</code>. I am having doubt what to synchronise whether the <code>HashMap</code> or the <code>Thread</code> in both the <code>Waiter</code> and <code>Notifier</code> class..</p>
  
  <pre><code>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&lt;Long, Thread&gt; map = new HashMap&lt;Long, Thread&gt;();
  
          ExecutorService executor = Executors.newFixedThreadPool(5);
          for (int i = 0; i &lt; 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&lt;Long, Thread&gt; map;
      ExecutorService executor = Executors.newFixedThreadPool(5);
  
      public Waiter(Map&lt;Long, Thread&gt; map) {
          this.map = map;
      }
  
      public void run() {
  
          ExecutorService executor = Executors.newFixedThreadPool(5);
  
          for (int i = 0; i &lt; 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&lt;Long, Thread&gt; map;
  
      public Notifier(Map&lt;Long, Thread&gt; map)
  
      {
          this.map = map;
      }
  
      public synchronized void run() {
  
          synchronized (map) {
  
              for (Map.Entry&lt;Long, Thread&gt; entry : map.entrySet()) {
  
                  System.out.println("stored threads in map are---&gt;" + map.get(entry.getKey()));
  
                  map.get(entry.getKey()).notify();
  
              }
  
          }
      }
  }
  
  class Runner implements Runnable {
  
      public void run() {
          System.out.println("runner invoked");
  
      }
  }
  </code></pre>