一、并发容器:
ConcurrentHashMap:
1、分段锁机制: 任意数量的读取线程可以并发的访问map,执行读取操作的线程和执行写入操作的线程可以并发的访问Map,并且一定数量的写入线程可以并发的修改Map。
2、无需再迭代过程中对容器加锁;
3、ConcurrentHashMap无法实现对Map加锁已提供独占访问,在HashMap及SynchrogazedMap中,获得Map的锁能防止其他线程访问这个Map;
4、大多数情况下,用ConcurrentHashMap代替同步Map能进一步提高代码的可伸缩性,只有当应用程序需要加锁Map以进行独占访问时,才应该放弃使用ConcurrentHashMap。
CopyOnWriteArrayList:
1、用于代替同步List,迭代期间不需要对容器进行加锁或复制;
2、 容器的线程安全性在于: 只要正确的发布一个事实不可变的对象,那么在访问该对象时就不需要进一步的同步,在每次修改时,都会创建并重新发布一个新的容器副本,从而实现可变性。
3、仅当迭代操作远远多于修改操作时,才应该使用“写入时复制”容器。
二、同步工具类:
1. 闭锁:
(1)延迟线程的进度直到其到达终止状态,可用来确保某些活动直到其他活动都完成后才继续执行;
(2)实现:CountDownLatch
public class TestHarness { public long timeTasks(int nThreads, final Runnable task) throws InterruptedException { final CountDownLatch startGate = new CountDownLatch(1); final CountDownLatch endGate = new CountDownLatch(nThreads); for(int i=0;i<nThreads;i++){ Thread t = new Thread(){ public void run(){ try{ startGate.await(); try { task.run(); }finally { endGate.countDown(); } }catch (InterruptedException ignored){ } } }; t.start(); } long start = System.nanoTime(); startGate.countDown(); endGate.await(); long end = System.nanoTime(); return end-start; } }
2、栅栏(Barrier)
(1)栅栏类似于闭锁,它能阻塞一组线程直到某个事件发生,它与闭锁的关键区别在于:所有线程必须同时到达栅栏,才能继续执行。闭锁用于等待事件,而栅栏用于等待线程。闭锁一旦打开将不会再关闭,栅栏打开后还可以重置以供下次使用。
(2)实现方式: CyclicBarrier(摘自http://www.itzhai.com/the-introduction-and-use-of-cyclicbarrier.html)
public class CyclicBarrierTest { public static void main(String[] args) throws IOException, InterruptedException { CyclicBarrier barrier = new CyclicBarrier(3); ExecutorService executor = Executors.newFixedThreadPool(3); executor.submit(new Thread(new Runner(barrier, "1号选手"))); executor.submit(new Thread(new Runner(barrier, "2号选手"))); executor.submit(new Thread(new Runner(barrier, "3号选手"))); executor.shutdown(); } static class Runner implements Runnable{ private CyclicBarrier barrier; private String name; public Runner(CyclicBarrier barrier, String name) { super(); this.barrier = barrier; this.name = name; } @Override public void run() { try { Thread.sleep(1000 * (new Random()).nextInt(8)); System.out.println(name + " 准备好了..."); barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(name + " 起跑!"); } } }