java - 是否可以在 hashmap 中存储线程对象?

标签 java multithreading collections concurrency core

我有一个场景,我调用大约10个Thread,每个Thread都必须等待,直到Notifier类通知我要通知特定的Thread,我正在做的是使用HashMap,其中Thread id作为keyThread实例作为值。稍后在 Notifier 中,我尝试通过遍历提供 Thread 实例的 map map.get(threadId) 来通知它,我尝试对其调用通知,但它抛出 IllegalmonitorException。我不确定在 WaiterNotifier 类中同步 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");

    }
}

最佳答案

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

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

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

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

并且,调用对象Runner的方法notify来停止等待并继续线程并离开同步块(synchronized block),如下所示:

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

但是,请考虑一下,用您当前的代码很难实现这些技巧,因为您必须重写几个部分,例如:使用位于 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(..){
               //..
            };
  }

}

关于java - 是否可以在 hashmap 中存储线程对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42831577/

相关文章:

collections - Backbone.js:如何访问嵌套集合的父模型?

java - Kotlin - kotlin 列表过滤器是否会创建一个新的列表对象?

java - 方法重载尝试给出名称冲突错误。不使用泛型

java - 如何减少Java构造函数的重复性和臃肿性?

java - 并行使用相同方法的线程

c++ - 使用 pthread_create 时出现奇怪的输出

java - 对象数组列表 - 最小值

java - 如何在 Java 中最小化/图标化 JWindow?

java - Apache 点燃。 QueryCursor 无需事务模式即可工作,即使直接声明事务也是如此。为什么?

python - 打印每个线程独有的语句