哪些Java集合是同步的(线程安全),哪些不是?

时间:2011-05-18 13:38:52

标签: java collections

哪些Java集合是同步的,哪些不是?

示例:HashSet未同步

11 个答案:

答案 0 :(得分:9)

有三组收藏。

  • Java 1.0集合,主要是遗留类。这包括Hashtable,Vector,Stack。这些是同步的,但我不建议你使用它们。属性可能是一个例外,但我不会在多线程上下文中使用它。
  • 1998年添加的Java 1.2集合在很大程度上取代了这些集合,但未同步,但可以使用Collections.synchronizedXxx()方法进行同步
  • 2004年添加的Java 5.0并发集合支持无锁,线程安全的集合。

简而言之,我建议你使用的任何系列都不会同步。

答案 1 :(得分:7)

您可以使用

获取Java Collection的同步版本
Collections.synchronizedCollection(Collection<T> c)

[javadoc]

答案 2 :(得分:7)

简单回答:Collection的单个实现没有被同步,因为 synchronized不是类属性,它只适用于方法和块。

我想,你想知道哪些实现是线程安全的,java集合框架中的哪些类可以安全地用在多线程环境中。

信息总是包含在javadoc(like here: Arraylist - 这不是线程安全的)

答案 3 :(得分:6)

线程安全集合-

  1. ConcurrentHashMap

线程安全,而不必同步整个映射 使用锁定完成写入时非常快的读取 在对象级别没有锁定 使用多个锁。

  1. SynchronizedHashMap

对象级同步 读取和写入均获得锁定 锁定收藏存在性能缺陷 可能引起争用

  1. 向量

  2. 哈希表

  3. CopyOnWriteArrayList

  4. CopyOnWriteArraySet

  5. 堆栈

所有这些都不是线程安全的

答案 4 :(得分:4)

Collection Interface中的ArrayList,LinkedList,HashSet,LinkedHashset和TreeSet以及HashMap,LinkedHashMap和Treemap都是非同步

集合界面中的向量是同步

答案 5 :(得分:1)

上一个例子是完全错误的。

首先,您不是从不同的线程访问刚刚同步的列表,您没有证明同步正在正确执行,您无法证明添加进程是原子的。其次,列表本身的synchronized子句是一种不好的做法,您不知道优化器是否会使用列表中的项来进行同步,从而导致意外行为。此外,您正在同步的是访问列表读/写中的元素,而不是列表本身。取出Collections.synchronized并查看输出。尝试多次。 请采取以下示例:

class ProcessSomething {
    private List<Integer> integerList = Collections.synchronizedList(new ArrayList<>());
    private void calculate() {
        for (int i = 0; i < 10000; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
            }
            integerList.add(new Random().nextInt(100));
        }
    }
    private void calculate2() {
        for (int i = 0; i < 10000; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
            }
            integerList.add(new Random().nextInt(100));
        }
    }
    public void process() {
        Long start = System.currentTimeMillis();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                calculate();
            }
        });
        t1.start();
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                calculate2();
            }
        });
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(ProcessSomething.class.getName()).log(Level.SEVERE, null, ex);
        }
        Long end = System.currentTimeMillis();
        System.out.println("Duration: " + (end - start));
        System.out.println("List size: " + integerList.size());
    }
}
public class App {
    public static void main(String[] args) {
        new ProcessSomething().process();
    }
}

答案 6 :(得分:0)

同步会降低性能。当然,Java集合不同步。但是Java提供了一个Synchronization Wrappers来同步Java Collection see link

for example:


    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Iterator;
    import java.util.List;

    public class SynchronizedListExample {

        public static void main(String[] args) {

            List<String> syncList = Collections.synchronizedList(new ArrayList<String>());

            syncList.add("one");//no need to synchronize here
            syncList.add("two");
            syncList.add("three");
            String st = syncList.get(0); //it is ok here => no need to synchronize

            // when iterating over a synchronized list, we need to synchronize access to the synchronized list
           //because if you don't synchronize here, synchList maybe be changed during iterating over it
            synchronized (syncList) {
                Iterator<String> iterator = syncList.iterator();
                while (iterator.hasNext()) {
                    System.out.println("item: " + iterator.next());
                }
            }

        }

    }

答案 7 :(得分:0)

java.util包中的所有集合类(Vector和Hashtable除外)都不是线程安全的。 仅有的两个旧集合是线程安全的:向量和哈希表。为什么? 原因是:同步可能非常昂贵! 您知道,Vector和Hashtable是Java历史悠久的两个集合,它们从一开始就是为线程安全而设计的(如果您有机会查看它们的源代码,您将看到它们的方法都是同步的!)。但是,它们很快暴露出多线程程序中的不良性能。如您所知,同步需要锁定,锁定始终需要花费时间来监视,从而降低了性能。 这就是为什么新集合(列表,集合,地图等)根本不提供并发控制以在单线程应用程序中提供最佳性能的原因。

答案 8 :(得分:0)

import java.util.Collections; //导入此

List<String> syncList = Collections.synchronizedList(new ArrayList<String>());

这是在Java中同步列表的方法。

答案 9 :(得分:0)

线程安全集合

  • 旧版 - Vector(父级为 List)和 Hashtable(父级为 Map
  • 同步集合使用 synchronized 监视器。 Collections.synchronizedCollections.synchronizedList()Collections.synchronizedSortedMap()Collections.synchronizedSet()...
  • 并发集合(Java 5)
    • Copy-On-Write(COW) - 比同步集合具有更好的性能,但具有更大的内存占用。修改数组时会创建新的数组副本(添加、设置、删除)。它是多读操作和后方修改的一个很好的变体。 CopyOnWriteArrayList, CopyOnWriteArraySet
    • Compare-And-Swap(CAS)[About] - ConcurrentLinkedQueue, ConcurrentSkipListMap
    • Lock 基于 - ConcurrentHashMapBlockingQueue 后代

答案 10 :(得分:-3)

我想集合API的每个实现都是用文档编写的。