一个简单多线程作业

题目要求

实现一个互评打分过程:

  • 创建一个线程池,为每个Employee开启一个线程。开启一个主持人线程;
  • 主持人线程在按照顺序确定当前给谁打分,并通知所有的Employee线程(10个);Employee线程接到通知后,在随机延时后打出一个随机分数;主持人收集到所有人打出的分数后,计算出被评分人的平均分。

思路分析

采用ReentrantLock实现“等待-通知”机制

代码实现

public class Main {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_NUMBER);
        // 开启主持人线程
        executorService.execute(new CompereThread());
        // 开启各个Employee线程
        for (int index = 1; index <= EMPLOYEE_NUMBER; index++) {
            executorService.execute(new EmployeeThread());
        }
        // 关闭线程池
        executorService.shutdown();
    }
}
public class Resource {
    // 总线程数目
    protected static final int THREAD_NUMBER = 11;
    // 参与打分的员工数目
    protected static final int EMPLOYEE_NUMBER = 10;
    // 总分数
    protected static float sumGrades = 0;
    // 每轮已经打分的人数
    protected static int sumEmployee = 0;
    // 锁
    protected static Lock lock = new ReentrantLock();
    // 条件队列1:Employee线程使用
    protected static Condition queue1 = lock.newCondition();
    // 条件队列2:主持人线程使用
    protected static Condition queue2 = lock.newCondition();
    // 本次互评是否结束
    protected static boolean finished = false;
}
// 主持人线程
public class CompereThread implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(CompereThread.class);

    @Override
    public void run() {
        // 主持人尝试获得锁(获得与否其实不影响,即使获得了锁,当条件不满足时,即:还有员工没有打分,同样被挂起而释放锁)但是await方法必须在lock 和 unlock之间使用
        lock.lock();
        try {
            for (int index = 1; index <= EMPLOYEE_NUMBER; index++) {
                logger.info("【---第{}轮打分开始!---】", index);
                // 等待所有人打分完毕 wait-notify机制
                while (sumEmployee != EMPLOYEE_NUMBER) {
                    // 条件不满足 主持人线程挂起 释放锁 等待Employee们打分
                    queue2.await();
                }
                // 条件满足 所有人打分完毕 继续
                // 计算平均分并打印
                logger.info("【Employee{}的平均分为:{}", index, (sumGrades / EMPLOYEE_NUMBER));
                logger.info("【---第{}轮打分结束!---】", index);
                logger.info(" ");
                // 初始化 为下一轮打分做准备
                sumGrades = 0;
                sumEmployee = 0;
                // 本轮打分结束 唤醒所有Employee开始下一轮打分
                queue1.signalAll();
            }
        } catch (Exception e) {
        }
        // 互评结束
        finished = true;
        // 手动释放锁
        lock.unlock();
    }
}
// 子员工线程
public class EmployeeThread implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(EmployeeThread.class);
    private static final int MAX_GRADE = 10;
    private static final int MAX_SLEEP_TIME = 3;

    @Override
    public void run() {
        float grade = 0;
        int cnt = 0;
        // 互评过程未结束
        try {
            while (!finished) {
                cnt++;
                // 加锁 保证对各个线程 sumGrades 和 sumEmployee 操作的原子性和可见性
                lock.lock();
                // 竞争到锁 打分
                // 随机延时 1-3s
                TimeUnit.SECONDS.sleep((new Random().nextInt(MAX_SLEEP_TIME) + 1));
                // 随机打分 1-10分
                grade = (new Random().nextInt(MAX_GRADE) + 1);
                sumGrades += grade;
                // 本轮已打分人数更新
                sumEmployee++;
                // 打印每轮次的打分信息
                logger.info("【Employee: {}】给第{}个工作人员打分为:{}——【当前总分】{} ", Thread.currentThread().getName(), cnt, grade, sumGrades);
                // 本轮是否结束
                if (sumEmployee >= EMPLOYEE_NUMBER) {
                    // 唤醒主持人线程开始下一轮
                    queue2.signal();
                }
                // 当前线程本轮打分结束 挂起 释放锁 本轮其他未打分线程去竞争 也防止重复打分
                queue1.await();
            }
        } catch (Exception e) {
        } finally {
            // 手动释放
            lock.unlock();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值