多线程模拟实现百米赛跑

题目: 设计并编写一个程序, 10名选手准备就绪后, 等待一名裁判吹哨开始比赛.

1. CountDownLatch

1.1 概念

使用 CountDownLatch 可以使线程在等待其他线程完成任务之后, 再继续执行自己的任务.

通过一个计数器, 当其他线程完成了自己的任务之后, 通过计数器-1的操作, 当计数器值为0的时候, 其他线程的操作就完成了, 接下来在等待的线程, 就会恢复状态, 执行自己的任务.

1.2 基础方法

  1. 在初始化的时候, 通过调用一个有参的构造方法, 来设置等待的线程数.
    在这里插入图片描述
  2. 通过调用 countDown() 方法, 让计数器减一
    在这里插入图片描述
  3. 通过调用 await() 方法, 让线程等待其他线程操作, 直到计数器为0, 再进行自己的操作
    在这里插入图片描述

2. 模拟实现百米赛跑

2.1 设计思路

  1. 这里通过一个CountDownLatch代表裁判, 初始化为1.
  2. 这里通过另一个CountDownLatch代表玩家, 初始化为10.
  3. 这里通过线程池去创建10个线程.
  4. 每个线程初始化的时候, 去调用裁判CountDownLatch的await()方法来进行准备, 相当于预备跑
  5. 当所有的线程都准备好之后, 裁判就调用countDown()方法, 吹哨开跑, 每个玩家就开始跑步.
  6. 他们的速度是随机的, 通过调用Random这个类来实现.
  7. 当玩家跑完步之后, 玩家CountDownLatch就调用countDown方法.
  8. 当计数器为0的时候, 比赛就结束了, 释放线程池. 结束比赛.

2.2 代码实现

package com.example.demo;


import lombok.SneakyThrows;

import java.util.Random;
import java.util.concurrent.*;


public class TEst {
    
    
    // begin 代表裁判 初始为 1
    private static CountDownLatch begin = new CountDownLatch(1);
    
    // end 代表玩家 初始为 10
    private static CountDownLatch end = new CountDownLatch(10);

    public static void main(String[] args) throws InterruptedException {
    
    
        // 首先创建线程池容量为10
        ExecutorService es = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
    
    
            // 创建 10 个线程
            es.submit(new Runnable() {
    
    
                @SneakyThrows
                @Override
                public void run() {
    
    
                    // 预备状态
                    System.out.println("参赛者"+Thread.currentThread().getName().substring(Thread.currentThread().getName().lastIndexOf('-')+1) + "已经准备好了");
                    // 等待裁判吹哨
                    begin.await();
                    // 开始跑步
                    System.out.println("参赛者"+Thread.currentThread().getName().substring(Thread.currentThread().getName().lastIndexOf('-')+1) + "开始跑步");
                    // 等待时间就是跑步的总时间
                    Thread.sleep(new Random().nextInt(10) * 10000);
                    // 跑步结束, 跑完了
                    System.out.println("参赛者"+Thread.currentThread().getName().substring(Thread.currentThread().getName().lastIndexOf('-')+1)+ "到达终点");
                    // 跑到重点, 计数器就减一
                    end.countDown();
                }
            });
        }
        // 等待 5s 就开始吹哨
        Thread.sleep(5000);
        System.out.println("开始比赛");
        // 裁判吹哨, 计数器减一
        begin.countDown();
        // 等待所有玩家到达终点
        end.await();
        System.out.println("比赛结束");
        // 关闭线程池
        es.shutdown();
    }
}

2.3 运行结果

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/wwzzzzzzzzzzzzz/article/details/127298806
今日推荐