jdk中提供了几个非常有用的工具类,分别是CountDownLatch,CyclicBarrier和semaphore exchanger
CountDownLatch:允许一个或者多个线程等待其他线程完成操作
public class CountDownLatchTest{
static CountDownLatch c = new CountDownLatch(2);
public static void main(String[] args){
new Thread(new Runnable(){
System.out.println(1);
c.countDown();
System.out.println(2);
c.countDown();
}).start();
c.await();
System.out.println("3");
}
}
CountDownLatch的构造函数接收一个int 型的参数作为计数器,当你等待n个点就传入n,当我们调用CountDownLatch的countdown方法时,n就会减一,CountDownLatch的await方法一直阻塞,直到n变成0,这里的n 指的是n个线程,或者是n个点,在用多线程时,只需要把countdownlatch传入即可。
同步屏障CyclicBarrier
他要做的事情是让一组线程达到一个屏障时被阻塞,直到最后一个线程达到一个屏障时,屏蔽才会开门,所有被屏蔽拦截的线程才能继续运行
应用伪代码:
public class CyclicBarrierTest{
static CyclicBarrier c=new CyclicBarrier(2);
public static void main(String[] args){
new Thread(
new Runnable(){
@overide
public void runnable(){
c.await();
System.out.println(1);
}
}
).start();
c.await();
System.out.printlN(2);
}
}
由于cpu分配时间片的不确定性,因此输出的结果1,2 也可能是2,1
CycilcBarrier 提供了一个更高级的构造函数(int parties , Runnable runnable)
runnable 表示在达到了临界点后优先执行runnable。
CycilcBarrier和coutdownlatch的区别
countdownlatch只能使用一次,cycilcBarrier可以使用多次,可以使用reset方法重置,所以cyclicbarrier能适用于更复杂的业务场景。例如计算错误,可以重置,并重新计算结果。
cyclicBarrier方法补充:getNumberWaiting 获得阻塞线程数量
isbroken 阻塞线程时否被中断
控制线程并发数 semaphore(信号量)
semaphore信号量用来控制同时访问特定资源的线程数量。它通过协调各个线程,以保证合理的使用公共资源
应用场景:可以用作流量控制,特别是公共资源的有限场景比如数据库连接,
public Class SemaphoreTest{
private static final int THREAD_COUNT=30;
private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(THREAD_COUNT);
private static Semaphore s = new Semaphore(20);
public static void main(String[] args){
threadPool.executor(new Runnable(){
public void runnable(){
s.acquire():
System.out.println("使用中。。。。。");
s.release();
}
}):
}
}
线程间交换数据exchanger
Exchanger 是一个线程间协作的工具类,exchanger用于进行线程间的数据交换,他提供一个交换点,在这个同步点,两个线程可以交换彼此间的数据。这两个线程通过exchange方法交换数据,如果第一个线程先执行exchange方法,它一直会等待第二个线程执行exchange方法,当两个线程执行到交换点时,两个线程将交换数据,将本线程产生的数据传递给对方
应用场景,主要用于两个线程间对产生的数据进行校验