线程安全的List经常在Java面试被问到,比如:线程安全的List有哪些等问题,下面我重点详解线程安全的List@mikechen
1.CopyOnWriteArrayList
CopyOnWriteArrayList是一种并发容器,它通过对底层数组进行复制来实现线程安全。
如下所示:
import java.util.concurrent.CopyOnWriteArrayList; public class CopyOnWriteArrayListExample { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); list.add("orange"); // 创建两个线程对List进行并发访问 Thread thread1 = new Thread(() -> { for (String fruit : list) { System.out.println("Thread 1: " + fruit); } }); Thread thread2 = new Thread(() -> { list.add("grape"); System.out.println("Thread 2: Added grape"); }); // 启动两个线程 thread1.start(); thread2.start(); } }
在上面的代码中,我们首先:创建了一个CopyOnWriteArrayList,并向其中添加了几个元素。
接着:我们创建了两个线程,其中一个线程对List进行遍历,另一个线程向List中添加元素。
由于CopyOnWriteArrayList是线程安全的,因此这两个线程可以并发地对List进行访问,而不会出现数据不一致的问题。
2.Collections.synchronizedList
Collections类提供了一种方便的方式来创建线程安全的List,即使用synchronizedList()方法对原List进行包装,从而使其支持并发访问。
如下所示:
import java.util.ArrayList; import java.util.Collections; import java.util.List; public class SynchronizedListExample { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("apple"); list.add("banana"); list.add("orange"); // 使用synchronizedList方法创建线程安全的List List<String> synchronizedList = Collections.synchronizedList(list); // 创建两个线程对List进行并发访问 Thread thread1 = new Thread(() -> { for (String fruit : synchronizedList) { System.out.println("Thread 1: " + fruit); } }); Thread thread2 = new Thread(() -> { synchronizedList.add("grape"); System.out.println("Thread 2: Added grape"); }); // 启动两个线程 thread1.start(); thread2.start(); } }
在上面的代码中,我们首先创建了一个普通的List,然后使用Collections.synchronizedList()方法创建了一个线程安全的List。
3.Vector
Vector是一种传统的线程安全List,它的实现方式是在每个方法上使用synchronized来进行同步。
如下所示:
public synchronized boolean add(E e) { modCount++; add(e, elementData, elementCount); return true; }
虽然Vector的实现方式比较简单,但是由于每个方法都需要加锁,所以在多线程高并发场景下效率会比较低。
4.ConcurrentLinkedDeque
ConcurrentLinkedDeque是一种非阻塞的线程安全双向队列。它的实现方式是使用一种称为”无锁队列”的算法来实现线程安全。
如下所示:
import java.util.concurrent.ConcurrentLinkedDeque; public class ConcurrentLinkedDequeExample { public static void main(String[] args) { ConcurrentLinkedDeque<String> deque = new ConcurrentLinkedDeque<>(); deque.addFirst("apple"); deque.addLast("banana"); deque.addLast("orange"); // 创建两个线程对Deque进行并发访问 Thread thread1 = new Thread(() -> { for (String fruit : deque) { System.out.println("Thread 1: " + fruit); } }); Thread thread2 = new Thread(() -> { deque.addLast("grape"); System.out.println("Thread 2: Added grape"); }); // 启动两个线程 thread1.start(); thread2.start(); } }
以上就是线程安全List的详解,更多线程安全,请查看:Java线程安全问题怎么解决?4种常见方式详解!
陈睿mikechen
10年+大厂架构经验,资深技术专家,就职于阿里巴巴、淘宝、百度等一线互联网大厂。
关注「mikechen」公众号,获取更多技术干货!
后台回复【面试】即可获取《史上最全阿里Java面试题总结》,后台回复【架构】,即可获取《阿里架构师进阶专题全部合集》