簡體   English   中英

是否可以在hashmap中存儲線程對象?

[英]is it possible to store thread objects inside hashmap?

我有一個場景,我調用了大約10個Thread ,並且每個Thread都必須等到Notifier類通知我要通知特定的Thread ,我正在做的事情是我正在使用HashMap並將Thread id作為key並將Thread實例作為值。 稍后在Notifier我試圖通過遍歷提供Thread實例的映射map.get(threadId)來通知它,並且嘗試在其上調用notify,但是它拋出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中。

否則,@ TJCrowder告訴您,您使用通知的方式是錯誤的。 這是因為您正在通過沒有線程鎖的對象map.get(entry.getKey()).notify(); )調用通知 而不是您應該調用對象Runnerinstance.notify() )的notify ,該對象具有線程鎖定,如您的代碼所示: instance.wait();

首先! 您必須與對象instance同步阻塞對象,該對象instance將使用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 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(..){
               //..
            };
  }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM