0

質問を編集して、非常にシンプルにしました。まず、同じファイルに 2 つのクラスがあります。HashMapClass: ConccurentHashMap のインスタンスを作成し、NewThread: hashMap を更新します。

public class HashMapClass {

public static volatile ConcurrentHashMap serverMap = new ConcurrentHashMap();

public static void main(String args[]) {

    NewThread nt = new NewThread();
    nt.start();
}
}

class NewThread extends Thread {

@Override
public void run() {
    HashMapClass.serverMap.put("Ishan", new Integer(3));

System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
  try {
        Thread.sleep(10000);
    } catch (InterruptedException ex) {
        Logger.getLogger(NewThread.class.getName()).log(Level.SEVERE, null, ex);
    }
    }
}

ここでは、hashMap が空ではないことを示していますが、他のクラス New Class からアクセスしようとすると空と表示されます

public class NewClass {

public static void main(String s[]) {
    System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
    Set setMap = HashMapClass.serverMap.entrySet();
    Iterator i = setMap.iterator();
    for (int f = 0; i.hasNext(); ++f) {
        Map.Entry me = (Map.Entry) i.next();
        System.out.println("key is" + me.getKey() + "value is :" + me.getValue());
    }
}

}

このクラスがデータで更新されることはありません。これで分かりやすくなったと思います。

4

2 に答える 2

5

HashMap is not thread safe so you need to introduce some form of synchronization if you need to share a HashMap accross threads.

Alternatively, and more simply, use a ConcurrentHashMap which is thread safe.

As a side not, you would probably benefit from reading the Java tutorial on concurrency, especially the part on Memory consistency errors.

EDIT

Following your comment, see a simple example that, I think, isolates your issue - the output on my machine is:

Hash map empty in main (1st attempt)? true
Hash map empty in run? false
Hash map empty in main (2nd attempt)? false

public class Test {

    public static ConcurrentMap serverMap = new ConcurrentHashMap();

    public static void main(String[] args) throws InterruptedException {
        NewThread nt = new NewThread();
        nt.start();
        System.out.println("Hash map empty in main (1st attempt)? " + serverMap.isEmpty());
        Thread.sleep(200);
        System.out.println("Hash map empty in main (2nd attempt)? " + serverMap.isEmpty());
    }

    static class NewThread extends Thread {

        @Override
        public void run() {
            serverMap.put("Ishan", new Integer(3));

            System.out.println("Hash map empty in run? " + serverMap.isEmpty());
        }
    }
}

2ND EDIT

You can apply the same logic from another class - just make sure you call NewThread.start and wait enough (or just call NewThread.run directly so that it is run in the same thread and you don't have to wait):

public class NewClass {

    public static void main(String s[]) throws InterruptedException {
        new Test.NewThread().start();
        System.out.println("Hash map is empty or not (1): " + Test.serverMap.isEmpty());
        Thread.sleep(100);
        System.out.println("Hash map is empty or not (2): " + Test.serverMap.isEmpty());
        Set setMap = Test.serverMap.entrySet();
        Iterator i = setMap.iterator();
        for (int f = 0; i.hasNext(); ++f) {
            Map.Entry me = (Map.Entry) i.next();
            System.out.println("key is" + me.getKey() + "value is :" + me.getValue());
        }
    }
}
于 2012-06-27T16:12:56.480 に答える
1

スレッドセーフがないため、HashMap は同期部分で処理する必要があります。

ConcurrentHashMapは同時実行性に優れています。ConcurrentHashMap は、読み取り中に Map をロックせず、書き込み時に Map 全体をロックしません。現在書かれているマップの部分をロックします。

ただし、反復中に ConcurrentHashMap が変更された場合、ConcurrentHashMap は ConcurrentModificationException をスローしないことに注意することが重要です。

編集されたコード:

問題は、HashMapClass と NewClass の実行でした。JVM がシャットダウンしたとき、HashMapClass の実行が完了した後、NewClass クラスを実行して、ヒープに保存されている ConcurrentHashMap に保存されている値を取得するにはどうすればよいでしょうか。 jvm が終了するとすぐに失われます。はい、ConcurrentHashMap は static とマークされているため、値はヒープの Memory-Area に格納されます

public class HashMapClass {

public static  ConcurrentHashMap<String,Integer> serverMap = new ConcurrentHashMap<String,Integer>();

public static void main(String args[]) {

    NewThread nt = new NewThread();
    nt.start();
    try {
        nt.join();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


    new NewClass().go();

  }
}

class NewThread extends Thread {


@Override
public void run() {

    HashMapClass.serverMap.put("Ishan", 3);

    System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());



    }
}

 class NewClass {

public void go() {
    System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
    for(Map.Entry<String,Integer> m : HashMapClass.serverMap.entrySet()){

       System.out.println(m.getKey()+" "+m.getValue());
  }

}
}
于 2012-06-27T16:37:09.630 に答える