关于 java.util.concurrent 您不知道的 5 件事
http://www.ibm.com/developerworks/cn/java/j-5things4.html
http://www.ibm.com/developerworks/cn/java/j-5things5.html
1 TimeUnit
2 CopyOnWriteArrayList
在CopyOnWriteArrayList 中含有一个数组:
/** The array, accessed only via getArray/setArray. */ private volatile transient Object[] array;
可以看出,volatile 修饰,所以可以线程安全的赋值(即在一个线程中赋值,另一个线程立刻可以发现这个赋值)。
Iterator 在这个数组上迭代
所有的变化的操作(如 add, set 等等),都运行在同步的情况下,如:
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return <tt>true</tt> (as specified by {@link Collection#add}) */ public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
可见修改时,copy 一个新的数组,在赋值回去。
应用情况:遍历次数远大于变化操作。
本质上讲,CopyOnWriteArrayList 很适合处理 ArrayList 经常让我们失败的这种场景:读取频繁,但很少有写操作的集合,例如 JavaBean 事件的 Listeners。
注意:当A 线程通过Iterator 对CopyOnWriteArrayList 迭代中,B 线程修改这个CopyOnWriteArrayList,则B 线程的修改A 线程是看不到的。且Iterator 不支持remove, set, and add 的操作,如果调用则报UnsupportedOperationException。
很奇怪,我认为应该可以看到啊?
答案: 确实看不到,因为Iterator 中保存的是旧的数组,一旦CopyOnWriteArrayList 有修改操作,会立即重新创建一个新的数组。(这个新的数组和Iterator 中的旧数组不是一个对象了)
测试程序:
/** * @author alf */ public class TestCopyOnWriteArrayList { @SuppressWarnings("unchecked") public static void main(String[] args) throws InterruptedException { final CopyOnWriteArrayList copyOnWriteArrayList = new CopyOnWriteArrayList(); copyOnWriteArrayList.add("11111"); copyOnWriteArrayList.add("22222"); copyOnWriteArrayList.add("33333"); copyOnWriteArrayList.add("44444"); copyOnWriteArrayList.add("55555"); Thread thread = new Thread(){ @Override public void run() { copyOnWriteArrayList.add("BBB"); copyOnWriteArrayList.set(4, "haha"); System.out.println("--------------"); } }; int i = 0; Iterator it = copyOnWriteArrayList.iterator(); while (it.hasNext()) { i++; if (i== 3) { thread.start(); thread.join(); } System.out.println(it.next()); } } }
测试结果为:
11111 22222 -------------- 33333 44444 55555
3 BlockingQueue
4 ConcurrentMap
5 SynchronousQueues
6 Semaphore
7 CountDownLatch
8 Executor
9 ExecutorService
10 ScheduledExecutorServices
11 Timeout 方法