使用ReentrantLock和ThreadPoolExecutor模拟抢课

这里主要是在场景下帮助理解ReentrantLock和线程池的使用。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class GrabCourseTask implements Runnable {
    private final String studentName;
    private static int availableSeats = 10; // 假设有10个名额
    private static final Lock lock = new ReentrantLock(); // 创建一个ReentrantLock实例

    public GrabCourseTask(String studentName) {
        this.studentName = studentName;
    }

    @Override
    public void run() {
        try {
            if(grabCourse()) {
                System.out.println(studentName + " 抢到了一个名额!");
            } else {
                System.out.println(studentName + " 没有抢到名额。");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println(studentName + " 在尝试抢课时被中断。");
        }
    }

    private boolean grabCourse() throws InterruptedException {
        // 尝试获取锁
        if(lock.tryLock()) {
            try {
                if (availableSeats > 0) {
                    availableSeats--; // 减少一个名额
                    // 模拟服务器处理抢课请求需要一定的时间
                    Thread.sleep(100);
                    return true;
                }
                return false;
            } finally {
                lock.unlock(); // 确保在操作完成后释放锁
            }
        } else {
            // 如果无法立即获取锁,则表示当前有其他线程正在操作名额,直接返回失败
            return false;
        }
    }
}
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CourseGrabbingSimulation {
    public static void main(String[] args) {
        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5, // 核心线程数
                10, // 最大线程数
                1, // 空闲线程存活时间
                TimeUnit.SECONDS, // 时间单位
                new ArrayBlockingQueue<>(5)); // 任务队列

        // 模拟多个学生抢课
        for (int i = 1; i <= 15; i++) {
            String studentName = "学生" + i;
            executor.execute(new GrabCourseTask(studentName));
        }

        // 关闭线程池
        executor.shutdown();
    }
}

在真实的抢课系统中,抢课的逻辑会更加复杂,需要考虑数据库的并发访问、事务处理、网络延迟等因素。
为了简化示例,这里使用了 ReentrantLock来控制对 availableSeats 的访问,保证了线程安全。在实际应用中,可能需要更复杂的并发控制机制。

相关推荐

  1. 使用ReentrantLockThreadPoolExecutor模拟

    2024-06-19 05:04:02       54 阅读
  2. SynchronizedReentranLock区别

    2024-06-19 05:04:02       27 阅读
  3. ReentrantLock

    2024-06-19 05:04:02       40 阅读
  4. Synchronized ReentrantLock 的区别

    2024-06-19 05:04:02       56 阅读
  5. 第一次使用ThreadPoolExecutor处理业务

    2024-06-19 05:04:02       52 阅读
  6. 第一次使用ThreadPoolExecutor遇到的问题

    2024-06-19 05:04:02       70 阅读
  7. with ThreadPoolExecutor() as executor的使用举例

    2024-06-19 05:04:02       53 阅读
  8. synchronized ReentrantLock 的区别是什么

    2024-06-19 05:04:02       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-19 05:04:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-19 05:04:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-19 05:04:02       82 阅读
  4. Python语言-面向对象

    2024-06-19 05:04:02       91 阅读

热门阅读

  1. 最大子段和问题

    2024-06-19 05:04:02       27 阅读
  2. 探索VtKLoader源码中THREE.BufferGeometry的奥秘

    2024-06-19 05:04:02       22 阅读
  3. 深入解析Postman接口测试工具:功能与应用详解

    2024-06-19 05:04:02       34 阅读
  4. thinkphp5模型的高级应用

    2024-06-19 05:04:02       33 阅读
  5. 主元素问题(蒙特卡罗方法)笔记

    2024-06-19 05:04:02       28 阅读
  6. SAP ABAP 锁对象的分类及其作用

    2024-06-19 05:04:02       39 阅读
  7. 超参数调优-通用深度学习篇(上)

    2024-06-19 05:04:02       51 阅读