java - 你必须同步并发集合吗?

标签 java collections concurrency

想象一下下面的例子: 一个应用程序启动两个线程。 Provider 类保存并发集合并将数据写入其中。消费者从集合中读取数据。

下面的代码是正确的还是我必须添加同步?

public class Application{
    public static void main(String...args) throws Exception{
        Provider p = new Provider();
        new Thread(p).start();
        new Thread(new Consumer(p)).start();

        // Make sure the example stops after 60 seconds
        Thread.sleep(1000*60);
        System.exit(0);
    }
}

/**The Provider (writes data to concurrent collection)*/
class Provider implements Runnable{

    private ConcurrentMap<Integer, String> map 
        = new ConcurrentHashMap<Integer, String>(20, 0.5f, 1);

    public void run(){
         Integer i = 1;
         while(true){
             try {
                 Thread.sleep(500);
             } catch (InterruptedException ignore) {
             }
             // Synchronization ?
             map.put(i, i.toString());
             i++;
         }
    }

    public ConcurrentMap<Integer, String> getMap(){
         // Synchronization ?
         return map;
    }

}

/**The Consumer (reads data from concurrent collection)*/
class Consumer implements Runnable{

    private Provider provider;

    public Consumer(Provider p){
        provider = p;
    }

    public void run(){
        while(true){
             try {
                 Thread.sleep(1000);
             } catch (InterruptedException ignore) {
             }
            // Synchronization ?
            ConcurrentMap<Integer, String> m = provider.getMap();
            if(m!=null)
                for(String s: m.values())
                    System.out.print(s); 
            System.out.println();               
        }
    }

}

最佳答案

来自ConcurrentHashMap documentation :

For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries. Similarly, Iterators, Spliterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They do not throw ConcurrentModificationException. However, iterators are designed to be used by only one thread at a time. Bear in mind that the results of aggregate status methods including size, isEmpty, and containsValue are typically useful only when a map is not undergoing concurrent updates in other threads. Otherwise the results of these methods reflect transient states that may be adequate for monitoring or estimation purposes, but not for program control.

所以您不需要同步,因为您不会得到ConcurrentModificationException。您是否想要取决于您的程序逻辑。

关于java - 你必须同步并发集合吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29793433/

相关文章:

java - 如何以相反的顺序迭代 LinkedList 元素?

java - scala 中的 cogroup 两个 RDD

java - 这个并发的遗留代码是否需要可变

c# - 将 List<DerivedClass> 转换为 List<BaseClass>

python - 如何使用 celery 使用 mongoengine 向 mongodb 插入数据

c# - 子任务与 WaitAll

java - 如何调用多个嵌套内部类的父方法

java - 你如何让 gradle 从我的 build.gradle 项目中的 Java 类访问字符串?

java - 如何使用 Wikipedia API 提取/解析我要查找的链接?

java - 调用扫描器后方法不会更新 GUI