Java模拟赛跑过程

Java并发面试中的一个经典问题——手写代码模拟赛跑过程。该问题考查CountDownLatch的用法,比Java实现生产者-消费者模型的考查更直接:

  • 对Java并发模型的理解
  • 对Java并发编程接口(CountDownLatch)的熟练程度
  • 简化问题的能力
  • bug free
  • coding style

JDK版本:oracle java 1.8.0_102

需要注意是“简化问题的能力”。建议读者在继续阅读之前,自己先实现一个版本,之后再与文中的代码比较,看哪种思路更简洁,实现更美观。

需求

问题很经典,则需求概括如下:

  • 所有选手就位后,裁判鸣枪开始比赛
  • 选手到达终点或中途退赛后,记录成绩
  • 所有选手都已记录成绩后,结束比赛

再次建议读者自己先实现一个版本,再继续阅读。

设计 && 实现

设计

题目描述很清晰,现简化需求并设计如下:

选手逐渐就位 -> 开始比赛 -> 选手逐渐跑到终点或发生异常 -> 比赛结束

在三个连接处各使用一个CountDownLatch即可。

实现

三个连接处分别命名为ready、start、end,参赛者数量racerCnt,则:

public class Race {

  public static void race(int racerCnt) throws InterruptedException {
    CountDownLatch ready = new CountDownLatch(racerCnt);
    CountDownLatch start = new CountDownLatch(1);
    CountDownLatch end = new CountDownLatch(racerCnt);

    for (int i = 0; i < racerCnt; i++) {
      final int racerNo = i;
      new Thread(new Runnable() {
        @Override
        public void run() {
          System.out.println("ready: " + racerNo);
          ready.countDown();
          try {
            start.await();
            System.out.println("start: " + racerNo);
          } catch (InterruptedException e) {
            System.out.println("I am hurt, and have to interrupt the race...");
            Thread.currentThread().interrupt();
          } finally {
            System.out.println("end: " + racerNo);
            end.countDown();
          }
        }
      }).start();
    }

    ready.await();
    System.out.println("********************** all ready!!! **********************");
    System.out.println("********************** will start soon **********************");
    start.countDown();
    end.await();
    System.out.println("********************** all end!!! **********************");
  }

  public static void main(String[] args) throws InterruptedException {
    race(5);
  }
}

选择一个比较乱的输出:

ready: 1
ready: 0
ready: 2
ready: 3
ready: 4
********************** all ready!!! **********************
********************** will start soon **********************
start: 1
start: 2
start: 3
end: 3
start: 0
end: 0
end: 2
end: 1
start: 4
end: 4
********************** all end!!! **********************

很明显:第一名是3号选手;最后一名是4号选手;3号跑完的时候,0号还没有开跑。

总结

用CountDownLatch模拟赛跑过程虽然简单,但能简洁、美观的实现却不容易,很考验面试者简化问题的能力。


本文链接:Java模拟赛跑过程
作者:猴子007
出处:https://monkeysayhi.github.io
本文基于 知识共享署名-相同方式共享 4.0 国际许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名及链接。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,866评论 25 708
  • 相关概念 面向对象的三个特征 封装,继承,多态.这个应该是人人皆知.有时候也会加上抽象. 多态的好处 允许不同类对...
    东经315度阅读 1,976评论 0 8
  • 无戒365极限挑战营 第6天 几个月前,好友丽丽说,她想开一个公众号,写写文章。当时我很赞成,因为丽丽本来就是学...
    落雪寻梅阅读 324评论 10 5
  • 所思,在远道! 轶名 阴阳潜移,春秋代序,岁月荏苒,云卷云舒。我们在...
    小佳同学阅读 407评论 0 1
  • 3. 在我日复一日的备课讲课中,我深深感受到,学生和老师之间是由心灵感应的,你的行为举止,他们都会感受到,同样,他...
    静梦园阅读 575评论 0 1