CountDownLatch、CyclieBarrier与SamePhore都可用来控制线程的执行,那么他们之间有什么区别呢
CountDownLatch
CountDowenlatch可以看成一个线程等待多个线程,当多个线程执行完毕后最后线程才会执行
话不多说。直接上代码
/** * 一个线程等待多个线程,当多个线程都执行后 * 等待的线程才会执行 * @author chen * */ public class CountDownLatchT { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(5); for(int i=0;i<5;i++) { new Thread(()->{ countDownLatch.countDown(); System.out.println(Thread.currentThread().getName()); },"线程"+i).start(); } countDownLatch.await(); System.out.println("main"); } }
可以看到,刚开始给要等待的线程数设置个初始值,这里为5,意思是要等待5个线程,在线程里,要显式的时候countDownLatch的countDown方法表明
当前线程已经到了,将要等待的线程数减1,然后继续执行自己的代码。要等待的那个线程这里是main线程要使用countDownLatch的await方法进行等待。
当所有线程都到达后并且都执行countdown方法后等待线程才会被唤醒执行。所以这段代码的结果是前面的5个线程都执行完后主线程才会执行。
CyclicBarrier
如果说countdownlatch是执行减操作,每到一个线程就减1,直到减为0,被阻塞的线程才执行的话。那么CyclicBarrier就可以看作是加操作了。先上代码。
/** * 所有线程通过cyclicBarrier的await方法阻塞,直到最后一个线程到达后 * 才唤醒所有线程,这时这些线程才能继续往下执行 * @author chen * */ public class CyclicBarrierT { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(5); for(int i=0; i<5;i++) { new Thread(()->{ System.out.println(Thread.currentThread().getName()+"start"); try { cyclicBarrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"end"); },"线程"+i).start(); } } }
CyclicBarrier的工作原理是多个线程等一个线程,当一个线程到达的时候就使用await方法进入屏障,直到最后一个线程到达屏障的时候
屏障才会解除,所有到屏障的线程才会被唤醒继续往下执行。
SamePhore
SamePhore是信号量的意思,它的使用场景是多个线程使用有限个资源的情况。可以类比停车位,当汽车数大于停车位的时候一次只能有若干
辆汽车进去停车场,当汽车从停车场开出来的时候其他汽车才能进入停车场。
上代码
/** * Semaphore限定一次只能有几个线程执行 * 线程进入前使用acquire获取执行权 * 结束后使用release释放执行权 * @author chen * */ public class SemaPhoreT { public static void main(String[] args) { Semaphore semaphore = new Semaphore(2); for(int i=0;i<10;i++) { new Thread(()->{ try { semaphore.acquire(); System.out.println(Thread.currentThread().getName()+"启动了"); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }finally { semaphore.release(); } },"线程"+i).start(); } } }
上面代码信号量定义为2,线程数为10,因此我们执行的时候可以看到每次只有2个线程在运行。