[英]Which Java Collections are synchronized(thread safe), which are not?
Which Java Collections are synchronized, which are not?哪些 Java 集合是同步的,哪些不是?
Example: HashSet is not synchronized示例:HashSet 不同步
There are three groups of Collections.共有三组集合。
Collections.synchronizedXxx()
methods 1998 年添加的 Java 1.2 集合在很大程度上取代了这些集合不是同步的,但可以使用Collections.synchronizedXxx()
方法进行同步In short, none of the collections I would recommend you use are synchronized.简而言之,我建议您使用的所有集合都不是同步的。
Thread safe Collections -线程安全集合 -
Thread safe without having to synchronize the whole map Very fast reads while write is done with a lock No locking at the object level Uses multitude of locks.线程安全,无需同步整个地图 使用锁完成写入时读取速度非常快 在对象级别没有锁定 使用多个锁。
Object level synchronization Both read and writes acquire a lock Locking the collection has a performance drawback May cause contention对象级同步 读写都获取锁 锁定集合有性能缺陷 可能导致争用
Vector向量
HashTable哈希表
CopyOnWriteArrayList复制写入数组列表
CopyOnWriteArraySet复制写入数组集
Stack堆
Rest all are not thread safe其余的都不是线程安全的
Easy answer: not a single implementation of Collection
is synchronized because synchronized
is not a class property, it is only applicable to methods and blocks.简单回答:没有一个Collection
实现是同步的,因为synchronized
不是类属性,它只适用于方法和块。
I guess, you want to know which implementations are thread safe , which classes from the java collection framework can safely be used in a multithreaded environment.我想,您想知道哪些实现是线程安全的,哪些来自 java 集合框架的类可以安全地用于多线程环境中。
The information is always included in the javadoc ( like here: Arraylist - which is not thread safe)该信息始终包含在 javadoc 中( 例如:Arraylist - 这不是线程安全的)
ArrayList, LinkedList, HashSet,LinkedHashset and TreeSet in Collection Interface and HashMap,LinkedHashMap and Treemap are all non-synchronized . Collection 接口中的ArrayList、LinkedList、HashSet、LinkedHashset 和TreeSet 以及HashMap、LinkedHashMap 和Treemap 都是非同步的。
Vector in Collection Interface is Synchronized集合接口中的向量是同步的
The previous example is totally wrong.前面的例子是完全错误的。
First of all, you are not accessing from different threads the list that you just synchronized, you have no prove that the synchronization is being performed properly, you cannot prove that the add process is atomic.首先,您没有从不同的线程访问您刚刚同步的列表,您无法证明同步正在正确执行,您无法证明添加过程是原子的。 Second the synchronized clause over the list itself is a bad practice, you don't know if the optimizer will use an item in the list to do the synchronization, leading to an unexpected behavior.其次,列表本身上的同步子句是一种不好的做法,您不知道优化器是否会使用列表中的项目进行同步,从而导致意外行为。 Also, what you're synchronizing is the access to the elements in the list read/write, not the list itself.此外,您正在同步的是对列表中元素的读取/写入访问,而不是列表本身。 Take out the Collections.synchronized and see the output.取出 Collections.synchronized 并查看输出。 Try many times.多试几次。 Please take following example:请举以下例子:
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();
}
}
All collection classes (except Vector and Hashtable) in the java.util package are not thread-safe. java.util 包中的所有集合类(Vector 和Hashtable 除外)都不是线程安全的。 The only two legacy collections are thread-safe: Vector and Hashtable.仅有的两个遗留集合是线程安全的:Vector 和 Hashtable。 WHY?为什么? Here's the reason: Synchronization can be very expensive!原因如下:同步可能非常昂贵! You know, Vector and Hashtable are the two collections exist early in Java history, and they are designed for thread-safe from the start (if you have chance to look at their source code, you will see their methods are all synchronized!).你知道,Vector 和 Hashtable 是 Java 历史早期存在的两个集合,它们从一开始就是为线程安全而设计的(如果你有机会查看它们的源代码,你会发现它们的方法都是同步的!)。 However, they quickly expose poor performance in multi-threaded programs.然而,它们很快暴露了多线程程序的性能不佳。 As you may know, synchronization requires locks which always take time to monitor, and that reduces the performance.您可能知道,同步需要锁,这总是需要时间来监控,这会降低性能。 That's why the new collections (List, Set, Map, etc) provide no concurrency control at all to provide maximum performance in single-threaded applications.这就是新集合(List、Set、Map 等)根本不提供并发控制以在单线程应用程序中提供最大性能的原因。
synchronize makes performance lower.同步使性能降低。 of course, Java collection is not synchronized.当然,Java集合不是同步的。 but Java provides a Synchronization Wrappers to synchronize Java Collection see link但是 Java 提供了一个 Synchronization Wrappers 来同步 Java Collection 见链接
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());
}
}
}
}
import java.util.Collections;导入 java.util.Collections; //Import this //导入这个
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());
This is how you can synchronise a list in java.这就是您如何在 Java 中同步列表。
Thread safe Collections线程安全集合
Vector
(parent is List
) and Hashtable
(parent is Map
)传统 - Vector
(父级为List
)和Hashtable
(父级为Map
)synchronized
monitor.同步集合使用synchronized
监视器。 Collections.synchronized
, Collections.synchronizedList()
, Collections.synchronizedSortedMap()
, Collections.synchronizedSet()
... Collections.synchronized
, Collections.synchronizedList()
, Collections.synchronizedSortedMap()
, Collections.synchronizedSet()
...Copy-On-Write(COW)
- has better performance then Synchronized collections, but has a bigger memory footprint. Copy-On-Write(COW)
- 比同步集合具有更好的性能,但具有更大的内存占用。 New copy of array is created when you modify it(add, set, remove).修改数组时会创建新的数组副本(添加、设置、删除)。 It is a good variant for multi read operations and rear modifications.它是多读操作和后修改的一个很好的变体。 CopyOnWriteArrayList
, CopyOnWriteArraySet
CopyOnWriteArrayList
, CopyOnWriteArraySet
Compare-And-Swap(CAS)
[About] - ConcurrentLinkedQueue
, ConcurrentSkipListMap
Compare-And-Swap(CAS)
[关于] - ConcurrentLinkedQueue
, ConcurrentSkipListMap
Lock
based - ConcurrentHashMap
, BlockingQueue
descendants基于Lock
- ConcurrentHashMap
, BlockingQueue
后代我猜集合 API 的每个实现都写在文档中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.