Java并发编程高级内容介绍

计数器:CountDownLatch

CountDownLatch类似于一个计数器,和Atomic类比较相近,操作是原子的,即多个线程同时只能有一个可以去操作。CountDownLatch对象设置一个初始的数字作为计数值,任何调用这个对象上的await()方法都会阻塞,直到这个计数器的计数值被其他的线程调用countDown()减为0为止。典型的应用场景就是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。例如在Zookeeper的使用过程中,由于客户端与服务器建立连接是异步调用的,因此主线程需要await()阻塞直至异步回调countDown()完成。

代码示例:

public class CountDownLatchTest {
 
 
    public static void main(String[] args) {
 
        final CountDownLatch countDownLatch = new CountDownLatch(2);
 
        Thread work1 = new Thread(new Runnable() {
            @Override
            public void run() {
 
                System.out.println(Thread.currentThread() + " doing work...start");
 
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                System.out.println(Thread.currentThread() + " doing work...end ");
                countDownLatch.countDown();
            }
        },"work1");
 
 
        Thread work2 = new Thread(new Runnable() {
            @Override
            public void run() {
 
                System.out.println(Thread.currentThread().getName() + " doing work...start");
 
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                System.out.println(Thread.currentThread().getName() + " doing work...end ");
                countDownLatch.countDown();
            }
        },"work2");
 
        work1.start();
        work2.start();
 
        try {
            countDownLatch.await();
            System.out.println("all workers finish ");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
 
 
    }
 
 
}

齐步走:CyclicBarrier

Barrier的意思是栅栏,就是让一组线程相互等待,直至所有线程都到齐了,那么就可以齐步走。Cyclic是循环的意思,就是说Barrier可以循环使用。CyclicBarrier主要的方法就是await(),较CountDownLatch的await()虽然都是阻塞,但是CyclicBarrier.await()有返回值int,即当前线程是第几个到达这个Barrier的线程。

构造CyclicBarrier时指定计数值,await() 方法每被调用一次,计数便会减少1,并阻塞住当前线程。当计数减至0时,阻塞解除,所有在此 CyclicBarrier 上面阻塞的线程开始运行。在这之后,如果再次调用 await() 方法,计数就又会变成 N-1,新一轮重新开始。在构造方法上还可以传递一个Runnable对象,阻塞解除时这个Runnable会得到运行。

CyclicBarrier有点“不见不散”的味道,想一想,如果某个成员因某种原因来不了Barrier这个地方,那么我们一直等待吗?实际中,如果来不了理应通知其他成员,别等了,回家吧!注意到CyclicBarrier.await()独有的BrokenBarrierException异常

Java并发编程高级内容介绍

代码示例:

public class CyclicBarrierTest {
 
    public static void main(String[] args) {
 
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(2, new Runnable() {
            @Override
            public void run() {
                System.out.println("都准备好啦!");
            }
        });
 
        Thread runman1 = new Thread(new Runnable() {
            @Override
            public void run() {
 
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                try {
                    cyclicBarrier.await();
                    System.out.println(Thread.currentThread().getName() + "i am ok");
 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        },"runman1");
 
 
        Thread runman2 = new Thread(new Runnable() {
            @Override
            public void run() {
 
                try {
                    cyclicBarrier.await();
                    System.out.println(Thread.currentThread().getName() + "i am ok");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }
        },"runman2");
 
        runman1.start();
        runman2.start();
 
    }
 
}

Callable And Future

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/e064b534a52cd1e6838f87aac1a9572f.html