Java 可以在hashmap中存储线程对象吗?
我有一个场景,我调用了大约10个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
线程
s,每个线程
都必须等待通知程序
类通知我要通知特定的线程
s,我所做的是使用HashMap
,其中线程
id为键
,而线程
实例为值。稍后在Notifier
中,我试图通过遍历mapmap.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(..){
//..
};
}
}