是否可以在 hashmap 中存储线程对象?
is it possible to store thread objects inside hashmap?
我有这样的场景,我调用了大约 10 个 Thread
,每个 Thread
必须等到 Notifier
class 通知我要通知特定 Thread
s,我正在做的是使用 HashMap
,Thread
id 作为 key
,Thread
实例作为值。稍后在 Notifier
中,我试图通过遍历地图 map.get(threadId)
来通知它,它给出了 Thread
实例,我试图调用它的通知,但它正在抛出 IllegalmonitorException
.我怀疑要同步 Waiter
和 Notifier
class..
中的 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();
首先!您必须同步块对象 instance
将使用 wait
方法阻塞线程,例如:
synchronized(instance){
try{
instance.wait()
}catch(...)
{
//Do Something else
}
}
然后,调用对象 Runner
的方法 notify
停止等待并继续线程并离开同步块,如下所示:
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(..){
//..
};
}
}
我有这样的场景,我调用了大约 10 个 Thread
,每个 Thread
必须等到 Notifier
class 通知我要通知特定 Thread
s,我正在做的是使用 HashMap
,Thread
id 作为 key
,Thread
实例作为值。稍后在 Notifier
中,我试图通过遍历地图 map.get(threadId)
来通知它,它给出了 Thread
实例,我试图调用它的通知,但它正在抛出 IllegalmonitorException
.我怀疑要同步 Waiter
和 Notifier
class..
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();
首先!您必须同步块对象 instance
将使用 wait
方法阻塞线程,例如:
synchronized(instance){
try{
instance.wait()
}catch(...)
{
//Do Something else
}
}
然后,调用对象 Runner
的方法 notify
停止等待并继续线程并离开同步块,如下所示:
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(..){
//..
};
}
}