diff --git a/SUMMARY.md b/SUMMARY.md index 6c0b2707..e92f5bb6 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -28,6 +28,7 @@ * [Java transient关键字](/java/basis/transient.md) * [Java finally与return执行顺序](/java/basis/finally-return.md) * [Java 8 新特性](/java/basis/java-8.md) + * [CountDownLatch,CyclicBarrier,Samaphore用法](java/basis/CountDownLatch,CyclicBarrier,Samaphore用法.md) * [Java并发](/java/concurrence.md) * [Java创建线程的三种方式](/java/concurrence/CreateThread.md) * [Java线程池](/java/concurrence/thread-pool.md) diff --git "a/java/basis/CountDownLatch\357\274\214CyclicBarrier\357\274\214Samaphore\347\224\250\346\263\225.md" "b/java/basis/CountDownLatch\357\274\214CyclicBarrier\357\274\214Samaphore\347\224\250\346\263\225.md" new file mode 100644 index 00000000..011d6735 --- /dev/null +++ "b/java/basis/CountDownLatch\357\274\214CyclicBarrier\357\274\214Samaphore\347\224\250\346\263\225.md" @@ -0,0 +1,507 @@ +在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore,今天我们就来学习一下这三个辅助类的用法。 + +以下是本文目录大纲: + +- CountDownLatch用法 +- CyclicBarrier用法 +- Semaphore用法 + +# CountDownLatch用法 + +CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。 + +CountDownLatch类只提供了一个构造器: + +```java +public CountDownLatch(int count) { }; //参数count为计数值 +``` + +然后下面这3个方法是CountDownLatch类中最重要的方法: + +```java +public void await() throws InterruptedException { }; //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 +public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行 +public void countDown() { }; //将count值减1 +``` + +下面看一个例子大家就清楚CountDownLatch的用法了: + +```java +public class Test { + public static void main(String[] args) { + final CountDownLatch latch = new CountDownLatch(2); + + new Thread(){ + public void run() { + try { + System.out.println("子线程"+Thread.currentThread().getName()+"正在执行"); + Thread.sleep(3000); + System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕"); + latch.countDown(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + }.start(); + + new Thread(){ + public void run() { + try { + System.out.println("子线程"+Thread.currentThread().getName()+"正在执行"); + Thread.sleep(3000); + System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕"); + latch.countDown(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + }.start(); + + try { + System.out.println("等待2个子线程执行完毕..."); + latch.await(); + System.out.println("2个子线程已经执行完毕"); + System.out.println("继续执行主线程"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} +``` + +执行结果: + +``` +线程Thread-0正在执行 +线程Thread-1正在执行 +等待2个子线程执行完毕... +线程Thread-0执行完毕 +线程Thread-1执行完毕 +2个子线程已经执行完毕 +继续执行主线程 +``` + +# CyclicBarrier用法 + +字面意思回环栅栏,通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。 + +CyclicBarrier类位于java.util.concurrent包下,CyclicBarrier提供2个构造器: + +```java +public CyclicBarrier(int parties, Runnable barrierAction) { +} + +public CyclicBarrier(int parties) { +} +``` + +参数`parties`指让多少个线程或者任务等待至`barrier`状态;参数barrierAction为当这些线程都达到barrier状态时会执行的内容。 + +然后CyclicBarrier中最重要的方法就是`await`方法,它有2个重载版本: + +```java +public int await() throws InterruptedException, BrokenBarrierException { }; +public int await(long timeout, TimeUnit unit)throws InterruptedException,BrokenBarrierException,TimeoutException { }; +``` + +第一个版本比较常用,用来挂起当前线程,直至所有线程都到达`barrier`状态再同时执行后续任务; + +第二个版本是让这些线程等待至一定的时间,如果还有线程没有到达barrier状态就直接让到达barrier的线程执行后续任务。 + +下面举几个例子就明白了: + +假若有若干个线程都要进行写数据操作,并且只有所有线程都完成写数据操作之后,这些线程才能继续做后面的事情,此时就可以利用CyclicBarrier了: + +```java +public class Test { + public static void main(String[] args) { + int N = 4; + CyclicBarrier barrier = new CyclicBarrier(N); + for(int i=0;i