唤醒、通知
  wait,notify,notifyAll是java的Object对象上的三个方法,多线程中可以用这些方法完成线程间的状态通知。
  notify是唤醒一个等待线程,notifyAll会唤醒所有等待线程。
  CountDownLatch主要提供的机制是当多个(具体数量等于初始化CountDownLatch时的count参数的值)线程都到达了预期状态或完成预期工作时触发事件,其他线程可以等待这个事件来触发后续工作。
  举个例子,大数据分拆给多个线程进行排序,比如主线程

CountDownLatch latch = new CountDownLatch(5);
for(int i=0;i<5;i++) {
threadPool.execute(new MyRunnable(latch,datas));
}
latch.await();
//do something 合并数据
  MyRunnable的实现代码如下
public void run() {
//do something数据排序
latch.countDown();
//继续自己线程的工作,与CyclicBarrier大的不同,稍后马上讲
}

  CyclicBarrier循环屏障,协同多个线程,让多个线程在这个屏障前等待,直到所有线程都到达了这个屏障时,再一起继续执行后面的动作。
  使用CyclicBarrier可以重写上面的排序代码
  主线程如下

CyclicBarrier barrier = new CyclicBarrier(5+1); //主线程也要消耗一个await,所以+1
for(int i=0;i<5;i++) {
threadPool.execute(new MyRunnable(barrier,datas));//如果线程池线程数过少,会发生死锁
}
barrier.await();
//合并数据
  MyRunnable代码如下
  public void run() {
  //数据排序
  barrier.await();
  }
  //全部 count+1 await之后(包括主线程),之后的代码才会一起执行
  信号量
  Semaphore用于管理信号量,与锁的大区别是,可以通过令牌的数量,控制并发数量,当管理的信号量只有1个时,退化到互斥锁。
  例如我们需要控制远程方法的并发量,代码如下
semaphore.acquire(count);
try {
//调用远程方法
}
finally {
semaphore.release(count);
}

  线程交换队列
  Exchanger用于在两个线程之间进行数据交换,线程会阻塞在Exchanger的exchange方法上,直到另外一个线程也到了同一个Exchanger的exchanger方法时,二者进行交换,然后两个线程继续执行自身相关代码。

public class TestExchanger {
static Exchanger exchanger = new Exchanger();
public static void main(String[] args) {
new Thread() {
public void run() {
int a = 1;
try {
a = (int) exchanger.exchange(a);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Thread1: "+a);
}
}.start();
new Thread() {
public void run() {
int a = 2;
try {
a = (int) exchanger.exchange(a);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Thread2: "+a);
}
}.start();
}
}
  输出结果:

  Thread2: 1
  Thread1: 2
  并发容器
  CopyOnWrite思路是在更改容器时,把容器写一份进行修改,保证正在读的线程不受影响,适合应用在读多写少的场景,因为写的时候重建一次容器。
  以Concurrent开头的容器尽量保证读不加锁,并且修改时不影响读,所以会达到比使用读写锁更高的并发性能