等待线程完成的CountDownLatch
功能:允许一个或多个线程等待其他线程完成操作。
- 在jdk1.5前,join可用于让当前线程等待join线程执行结束,原理是不停检查join线程是否存活,如果join线程存活则让当前线程一直等待;join线程终止后,调用notifyAll()方法。
- 在jdk1.5后,并发包提供了CountDownLatch方法来实现join功能,并且功能比join更多。
详解:CountDownLatch构造函数接收一个int类型参数作为计数器,传入N代表等待N个点完成。调用CountDownLatch的countDown()方法时,计数器N会减1,同时CountDownLatch的await()方法会阻塞当前线程,直至N减为0。
同步屏障CyclicBarrier
功能:让一组线程达到一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。
详解:CyclicBarrier默认构造方法是CyclicBarrier(int parties),其参数表示屏障拦截的线程数量,每个线程调用await()方法表明自己已经到达屏障,然后该线程被阻塞。另外一个高级构造方法CyclicBarrier(int parties, Runnable barrierAction),在线程到达屏障时,优先执行barrierAction,可方便处理更复杂业务。
CyclicBarrier和CountDownLatch的区别
- CountDownLatch的计数器只能用一次,CyclicBarrier计数器可以重置,所以后者可以应对更复杂的场景;
- CyclicBarrier还提供了例如getNumberWaiting()获取阻塞线程个数,以及IsBroken()返回阻塞线程是否被中断。
控制并发线程数的Semaphore
功能:Semaphore(信号量)用来控制同时访问线程资源的线程数量,通过协调各个线程,保证合理使用公共资源。
详解:Semaphore构造方法Semaphore(int permits),permits表示可用的许可证数量,也就是最大并发数。使用时,首先用acquire()方法获取一个许可证,用完之后调用release()方法归还许可证。此外还可用tryAcquire()方法尝试获取许可证。
- 应用场景
可用于流量控制,特别是公共资源有限的场景,比如数据库连接。例如“要读取几万个文件的数据,由于是IO密集型任务,可以启动30个线程并发读取。当读取到内存后,下一步存储到数据库中时,由于数据库仅有10个连接,此时必须控制仅有10个线程同时获取数据库连接保存数据,这里就可以用到Semaphore作流量控制。” - 其他方法
- int availablePermits(): 返回信号量中当前可用的许可证数量;
- int getQueueLength(): 返回正在等待许可证的线程数量;
- boolean hasQueuedThreads(): 是否有线程正在等待获取许可证;
- [protected] void reducePermits(int reduction): 减少reduction个许可证;
- [protected] Collection getQueuedThreads(): 返回所有等待获取许可证的线程集合;
线程间交换数据的Exchanger
功能:Exchanger是一个用于线程间协作的工具类,可用于线程间数据交换。
详解:提供一个同步点,在同步点两个线程可以交换彼此数据。这两个线程通过exchange()方法交换数据,如果一个线程先执行exchange()方法,它会等待另一个线程执行exchange()方法,当两个线程同时到达同步点时,即可交换数据,将己方数据交换给对方。(如果两个线程中有一个长时间不确定是否执行exchange()方法,可采用exchange(V x, long timeout, TimeUnit unit)来设置最大等待时长)