0

我已经编辑了我的问题并使其非常简单。首先在同一个文件中有两个类 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 不是线程安全的,因此如果您需要跨线程共享 HashMap,则需要引入某种形式的同步。

或者,更简单地说,使用线程安全的 ConcurrentHashMap

另一方面,您可能会从阅读有关并发的 Java 教程中受益,尤其是有关内存一致性错误的部分。

编辑

根据您的评论,请看一个简单的示例,我认为该示例可以隔离您的问题-我机器上的输出是:

主要的哈希映射为空(第一次尝试)?真正的
哈希图在运行中为空?主要的虚假
哈希映射为空(第二次尝试)?错误的

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());
        }
    }
}

第二次编辑

您可以从另一个类应用相同的逻辑 - 只需确保调用 NewThread.start 并等待足够长的时间(或者直接调用 NewThread.run 以便它在同一个线程中运行而您不必等待):

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。它将锁定当前正在编写的 Map 部分。

但重要的是要注意,如果 ConcurrentHashMap 在迭代期间发生更改,ConcurrentHashMap 不会抛出 ConcurrentModificationException。

编辑代码:

问题是 HashMapClass 和 NewClass 的执行,当 JVM 关闭时,HashMapClass 执行完成后,我们如何运行 NewClass 类并尝试检索存储在 ConcurrentHashMap 中的值,ConcurrentHashMap 存储在 Heap 上,这就是全部jvm 终止后立即丢失。是的,因为 ConcurrentHashMap 被标记为静态,所以值存储在堆的内存区域中

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 回答