Java 可以在hashmap中存储线程对象吗?

Java 可以在hashmap中存储线程对象吗?,java,multithreading,collections,concurrency,core,Java,Multithreading,Collections,Concurrency,Core,我有一个场景,我调用了大约10个线程s,每个线程都必须等待通知程序类通知我要通知特定的线程s,我所做的是使用HashMap,其中线程id为键,而线程实例为值。稍后在Notifier中,我试图通过遍历mapmap.get(threadId)来通知它,它给出了Thread实例,我试图调用notify,但它抛出了IllegalmonitorException。我怀疑在waterer和Notifier类中是同步HashMap还是同步Thread package com.cgi.sample.jms.re

我有一个场景,我调用了大约10个
线程
s,每个
线程
都必须等待
通知程序
类通知我要通知特定的
线程
s,我所做的是使用
HashMap
,其中
线程
id为
,而
线程
实例为值。稍后在
Notifier
中,我试图通过遍历map
map.get(threadId)
来通知它,它给出了
Thread
实例,我试图调用notify,但它抛出了
IllegalmonitorException
。我怀疑在
waterer
Notifier
类中是同步
HashMap
还是同步
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");

    }
}
package com.cgi.sample.jms.requestor;
导入java.util.HashMap;
导入java.util.Map;
导入java.util.UUID;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
公共类请求程序应用程序{
私有最终对象锁=新对象();
公共静态字符串correlationId;
公共静态字符串getCorrelationId(){
correlationId=UUID.randomUUID().toString();
返回相关ID;
}
公共静态void main(字符串args[])引发异常{
Map Map=newhashmap();
ExecutorService executor=Executors.newFixedThreadPool(5);
对于(int i=0;i<2;i++){
服务员=新服务员(地图);
执行者,执行者(侍者);
通知程序通知程序=新通知程序(映射);
执行人。执行人(通知人);
}
System.out.println(“所有线程都已启动”);
}
}
类服务员实现可运行{
地图;
ExecutorService executor=Executors.newFixedThreadPool(5);
公共服务生(地图){
this.map=map;
}
公开募捐{
ExecutorService executor=Executors.newFixedThreadPool(5);
对于(int i=0;i<2;i++){
Runner实例=新的Runner();
System.out.println(“执行线程“+”和“+线程.currentThread().getName()”);
long threadId=Thread.currentThread().getId();
字符串threadname=Thread.currentThread().getName();
执行人执行(实例);
同步(地图){
put(threadId,Thread.currentThread());
试一试{
instance.wait();
System.out.println(threadname+“线程进入等待状态!!!”;
//Thread.currentThread().wait();
System.out.println(threadname+“线程从等待中醒来!!!”;
}捕捉(中断异常e){
e、 printStackTrace();
}
}
}
}
}
类通知程序实现可运行{
地图;
公共通知程序(映射)
{
this.map=map;
}
公共同步的无效运行(){
同步(地图){
对于(Map.Entry:Map.entrySet()){
System.out.println(“map中存储的线程是-->”+map.get(entry.getKey());
map.get(entry.getKey()).notify();
}
}
}
}
类运行程序实现可运行{
公开募捐{
System.out.println(“调用运行程序”);
}
}

您的问题的答案是:。因为线程是一个对象,它可以存储到HashMap中

另外,@T.J.Crowder告诉你,你使用notify的方式是错误的。这是因为您正在对没有线程锁的对象调用通知(
map.get(entry.getKey()).notify();
)。相反,您应该调用对象的
notify
instance.notify()
)的
notify
,该对象拥有线程锁,正如您的代码所示:
instance.wait()

首先!您必须同步阻塞对象
实例
,该对象将使用
wait
方法阻塞线程,如:

synchronized(instance){ 
  try{
    instance.wait() 
  }catch(...)
  {
     //Do Something else
  }
}
并且,调用对象
Runner
的方法
notify
,停止等待,继续线程并离开syncrhonized块,如下所示:

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

但是,考虑到您当前的代码很难实现此提示,因为您必须重写多个部分,例如:使用位于for循环上下文中的对象来阻止线程的代码

for(int i=0;i<2;i++){
Runner实例=新的Runner();
//...
同步(地图){
put(threadId,Thread.currentThread());
试一试{
instance.wait();//您正在阻止在For循环中声明的实例。
}捕获(…){
//..
};
}
}

“是否可以在hashmap中存储线程对象?”是的,但这不是您的问题。您的问题是从不是对象监视器所有者的线程调用对象上的
notify
,这告诉您。由于您没有显示
notify
调用,我们无法帮助您。您应该避免在线程对象上进行同步,并且您绝对不应该调用
Thread.wait()
Thread.notify()
。原因是,
Thread
类本身利用
wait()
notify()
实现自己的目的。一个好的经验法则是永远不要在任何库对象上同步。相反,您可以创建一个
private final Object lock=new Object()
并在此基础上进行同步。您能告诉我如何获取映射中线程实例的RunnerInstance吗?请检查此链接:
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(..){
               //..
            };
  }

}