java并发之同步工具类一之闭锁Latch

java同步工具类(指jdk1.5版本)主要有闭锁(Latch)、信号灯(semaphore)和栅栏(barrier)。本篇作为开篇,先讲闭锁。闭锁就相当于一扇门,在制定的线程到达后这扇门才打开,后续所有线程可以通过,否则就一直处于阻塞状态。用于确保某些活动(这里可以理解为子线程)都完成后再继续执行下去(主线程)。如游戏中所有玩家就绪后才能点击开始,测试并发代码块真正的执行时间等(当我们在测试多线程的时候,总会有部分线程先启动,部分后启动,毕竟创建线程本身也需要时间,也就是多个线程会处在不同的初始条件下,这样测试出来的执行时间会有偏差,特别是线程非常多的时候,而闭锁可以在先启动的线程会等到所有后面启动的线程都启动完毕后再一起开始)。
如下面的代码引用了一个同样的场景——跑步比赛,只有所有运动员sprotMan都准备就绪后,裁判judge才能执行开始比赛。当所有运动员都结束比赛(到达终点或者放弃比赛),整场比赛才算结束。

import java.util.concurrent.CountDownLatch;

/**
 *
 * @author Jerry 比赛与Latch
 * @date 2017/12/24 0024
 */
public class Judge {
    public static void main(String[] args) {
        int joinMatchCnt = 5;//参加比赛的人数
        CountDownLatch beginMatchFlag = new CountDownLatch(1);
        CountDownLatch finishFlag = new CountDownLatch(joinMatchCnt);
        System.out.println("比赛准备开始.....");
        for (int i = 1; i <= joinMatchCnt; i++) {
            Thread t = new Thread(new Sportsman(beginMatchFlag, finishFlag, i + "号"));
            System.out.println("运动员"+i + "号已就位");
            t.start();//所有运动员都到指定位置就绪
        }
        beginMatchFlag.countDown();//裁判吹哨
        try {
            finishFlag.await();//裁判等待运动员跑完
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("比赛结束.....");
    }

    static class Sportsman implements Runnable {
        private CountDownLatch beginMatchFlag;
        private CountDownLatch finishFlag;
        private String name;

        public Sportsman(CountDownLatch beginMatchFlag, CountDownLatch finishFlag, String name) {
            this.beginMatchFlag = beginMatchFlag;
            this.finishFlag = finishFlag;
            this.name = name;
        }

        @Override
        public void run() {
            try {
                beginMatchFlag.await();//等待裁判比赛开始
                try {
                    running();
                } finally {
                    finishFlag.countDown();//运动员跑到终点,这里要放在finally中,如运动员跑步受伤,立即终止个人成绩
                }
                System.out.println("运动员" + name + "跑到终点线");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }

        private void running() {
            try {
                System.out.println("运动员" + name + "开始比赛");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

运行的结果如下

比赛准备开始.....
运动员1号已就位
运动员2号已就位
运动员3号已就位
运动员4号已就位
运动员5号已就位
运动员1号开始比赛
运动员2号开始比赛
运动员3号开始比赛
运动员4号开始比赛
运动员5号开始比赛
运动员1号跑到终点线
运动员3号跑到终点线
运动员2号跑到终点线
运动员4号跑到终点线
运动员5号跑到终点线
比赛结束.....

猜你喜欢

转载自blog.csdn.net/jerryJavaCoding/article/details/78884843