【Java多线程系列五】列表类
一些列表类及其特性
类 | 线程安全 | Iterator | 特性 | 说明 |
Vector | 是 | fail-fast | 内部方法用synchronized修饰,因此执行效率较低 |
1. 线程安全的列表类并不意味着调用它的代码就一定线程安全 2. 只有CopyOnWriteArrayList能支持在遍历时修改列表元素 |
ArrayList | 否 | fail-fast | 在多线程环境中使用不当易出错 | |
Collections.synchronizedList | 是 | fail-fast | Collections.synchronizedList可以得到线程安全的列表,与Vector类似 | |
CopyOnWriteArrayList | 是 | fail-safe | 每个线程先复制一份并把地址指向新list,在新的list上操作,因此最终结果未必符合预期,适用于经常需要读但很少修改的场景 |
以下代码模拟多线程环境下,各个类Iterator机制的表现
package com.concurrent.test; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Vector; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; /** * 多线程操作列表 */ public class ThreadListTest { public void multipleThreadArrayList(final List<Integer> list) throws InterruptedException { int count = 10; for (int i = 0; i < count; i++) { list.add(i); } final CountDownLatch countDownLatch = new CountDownLatch(2); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } for (Integer integer : list) { System.out.println(integer); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } countDownLatch.countDown(); } },"foreach-Thread").start(); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("ThreadId:" + Thread.currentThread().getId() + " remove " + list.remove(0)); countDownLatch.countDown(); } },"remove-Thread").start(); countDownLatch.await(); } public static void main(String[] args) throws InterruptedException { ThreadListTest test = new ThreadListTest(); List<Integer> list ; list = new Vector<>();// Vector只保证内部方法线程安全 list = new ArrayList<>();// ArrayList效率比Vector高,但非线程安全 list = Collections.synchronizedList(new ArrayList<Integer>());// Collections.synchronizedList与Vector异曲同工 list = new CopyOnWriteArrayList<>();// CopyOnWriteArrayList线程安全:每个线程先复制一份并把地址指向新list,在新的list上操作,因此最终结果未必符合预期 test.multipleThreadArrayList(list); System.out.println(list.toString()); } }