1. Semaphore 计数信号量
1. 通常用于限制可以访问某些资源(物理或逻辑的)的线程数目
2. 调用 acquire() 时无法保持同步锁,因为这会阻止将项返回到线程池中。
3. 将信号量初始化为 1,使得它在使用时最多只有一个可用的许可,从而可用作一个相互排斥的锁。这通常也称为二进制信号量,
4. 此类的构造方法可选地接受一个公平 参数
5. 主要方法:
1. acquire() 从此信号量获取一个许可,在提供一个许可前一直将线程阻塞,否则线程被中断。
2. release() 释放一个许可,将其返回给信号量。
6. 例如:
try {
sema.acquire();
System.out.println(Thread.currentThread().getId() + "进来了...");
System.out.println(Thread.currentThread().getId() + "出去了...");
Thread.sleep(100);
sema.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
2. CyclicBarrier
1. 一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。
2. CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。
若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。
3. 构造方法:
CyclicBarrier(int parties)
CyclicBarrier(int parties, Runnable barrierAction)
4. 主要方法:
1. int await() 在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
2. int getNumberWaiting() 返回当前在屏障处等待的参与者数目。
3. CountDownLatch
1. 在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
2. 调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。
3. 之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。
4. 它不要求调用 countDown 方法的线程等到计数到达零时才继续,而在所有线程都能通过之前,它只是阻止任何线程继续通过一个 await。
5. 主要方法:
1. await() 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断。
2. countDown() 递减锁存器的计数,如果计数到达零,则释放所有等待的线程。
3. getCount() 返回当前计数。
4. Exchanger
1. 可以在对中对元素进行配对和交换的线程的同步点。
2. 主要方法:
1. exchange(V x) 等待另一个线程到达此交换点(除非当前线程被中断),然后将给定的对象传送给该线程,并接收该线程的对象。
3. 示例:
@Override
public void run() {
try {
Thread.sleep(random.nextInt(2000));
System.out.println(Thread.currentThread().getId()+"到了...");
String msg = exchanger.exchange("我是线程:"+Thread.currentThread().getId());
System.out.println(Thread.currentThread().getId()+"——打印:"+msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
5. BlockingQueue
1. 实现类:ArrayBlockingQueue, DelayQueue, LinkedBlockingDeque, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue
2. 主要方法:
抛出异常 特殊值 阻塞 超时
插入 add(e) offer(e) put(e) offer(e, time, unit)
移除 remove() poll() take() poll(time, unit)
检查 element() peek() 不可用 不可用