哪些Java集合是同步的(线程安全),哪些不是?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哪些Java集合是同步的(线程安全),哪些不是?相关的知识,希望对你有一定的参考价值。
哪些Java集合是同步的,哪些不是?
示例:HashSet未同步
有三组收藏。
- Java 1.0集合主要是遗留类。这包括Hashtable,Vector,Stack。这些是同步的,但我不建议你使用它们。属性可能是一个例外,但我不会在多线程上下文中使用它。
- 1998年添加的Java 1.2集合在很大程度上取代了这些集合,它们不是同步的,但可以使用
Collections.synchronizedXxx()
方法进行同步 - 2004年添加的Java 5.0并发集合支持无锁,线程安全的集合。
简而言之,我建议您使用的任何集合都不会同步。
您可以获得Java Collection
的同步版本
Collections.synchronizedCollection(Collection<T> c)
[Qazxswpoi]
简单的回答:没有一个javadoc的实现是同步的,因为Collection
不是类属性,它只适用于方法和块。
我想,你想知道哪些实现是线程安全的,java集合框架中的哪些类可以安全地在多线程环境中使用。
该信息始终包含在javadoc中(synchronized
- 这不是线程安全的)
线程安全集合 -
- 的ConcurrentHashMap
线程安全而不必同步整个映射使用锁完成写入时非常快速读取在对象级别没有锁定使用多个锁定。
- SynchronizedHashMap
对象级同步读取和写入都获取锁定锁定集合具有性能缺陷可能导致争用
- 向量
- 哈希表
- 的CopyOnWriteArrayList
- CopyOnWriteArraySet
- 堆
休息都不是线程安全的
Collection接口和HashMap中的ArrayList,LinkedList,HashSet,LinkedHashset和TreeSet,LinkedHashMap和Treemap都是非同步的。
集合接口中的向量已同步
前面的例子是完全错误的。
首先,您不是从不同的线程访问刚刚同步的列表,您没有证明同步正在正确执行,您无法证明添加过程是原子的。其次,列表本身的synchronized子句是一种不好的做法,您不知道优化器是否会使用列表中的项来进行同步,从而导致意外行为。此外,您正在同步的是访问列表读/写中的元素,而不是列表本身。取出Collections.synchronized并查看输出。尝试多次。请采取以下示例:
like here: Arraylist
同步使性能降低。当然,Java集合不同步。但是Java提供了一个Synchronization Wrappers来同步Java Collection 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();
}
}
see link
java.util包中的所有集合类(Vector和Hashtable除外)都不是线程安全的。只有两个遗留系列是线程安全的:Vector和Hashtable。为什么?原因如下:同步可能非常昂贵!你知道,Vector和Hashtable是Java历史早期存在的两个集合,它们从一开始就设计用于线程安全(如果你有机会查看它们的源代码,你会发现它们的方法都是同步的!)。但是,它们很快就会在多线程程序中暴露出糟糕的性能。您可能知道,同步需要锁,这些锁总是需要时间来监控,这会降低性能。这就是新集合(List,Set,Map等)根本不提供并发控制以在单线程应用程序中提供最大性能的原因。
我想集合API的每个实现都是用文档编写的。
以上是关于哪些Java集合是同步的(线程安全),哪些不是?的主要内容,如果未能解决你的问题,请参考以下文章