线程池案例

秒杀

需求

  • 10个礼物20个客户抢
  • 随机10个客户获取礼物,另外10无法获取礼物

任务类

  • 记得给共享资源加锁
public class MyTask implements Runnable{
      // 礼物列表
    private  ArrayList<String> gifts ;

    // 用户名
    private String username;

    public MyTask( String username, ArrayList<String> gifts) {
        this.username = username;
        this.gifts = gifts;
    }

    @Override
    public void run() {
        // 模拟网络延迟
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 加锁 锁对象是gifts 保证线程安全
        synchronized (gifts) {
            // 抢礼物
            grabGift();
        }
    }

    // 抢礼物
    private void grabGift() {
        if (gifts.isEmpty()) {
            System.out.println("礼物已经被抢完了," + username + "没有抢到礼物");
            return;
        }

        // 输出礼物信息 随机抢一个
        System.out.println(username + "抢到了" + gifts.remove((int) (Math.random() * gifts.size()))) ;
    }


}

测试

1、创建线程池
2、执行任务
3、关闭线程池

// 礼物列表 有10个礼物
ArrayList<String> gifts = new ArrayList<String>() {{
  add("iPhone 12");
  add("MacBook Pro");
  add("iPad Pro");
  add("Apple Watch");
  add("AirPods Pro");
  add("HomePod");
  add("Apple TV");
  add("Apple Music");
  add("Apple Arcade");
  add("Apple Fitness");
}};


// 使用线程池 模拟20个用户同时抢礼物
ExecutorService executorService = Executors.newFixedThreadPool(7);
for (int i = 0; i < 20; i++) {
  executorService.execute(new MyTask("用户" + i, gifts));
}
// 关闭线程池
executorService.shutdown();

结果

在这里插入图片描述

双人取款机

ATM任务类

  • 默认同一个账户id等同于同一个锁对象
  • 取款的时候加锁,去完款就解锁
public class ATMTask implements Runnable{
    private String accountId;
    private double amount;
    private static Map<String, Double> balanceMap = new HashMap<>();
    private static final Map<String, Object> lockMap = new ConcurrentHashMap<>();

    static {
        balanceMap.put("1", 1000.0);
        balanceMap.put("2", 1000.0);
    }

    public ATMTask(String accountId, double amount) {
        this.accountId = accountId;
        this.amount = amount;
    }

    private double getBalance(String accountId) {
        return balanceMap.get(accountId);
    }

    private void updateBalance(String accountId, double amount) {
        if (getBalance(accountId) < amount) {
            System.out.println("账户余额不足");
            return;
        } else {
            System.out.println("用户" + accountId + "取款成功,取款金额:" + amount);
            balanceMap.put(accountId, getBalance(accountId) - amount);
            // 移除锁对象
            lockMap.remove(accountId);
        }
    }

    /**
     * 这个方法接受一个账户ID作为参数,
     * 然后检查lockMap中是否已经存在对应该账户ID的锁对象。
     * 如果不存在,它会使用putIfAbsent方法添加一个新的锁对象到lockMap中。
     * 这个方法最终返回账户ID对应的锁对象。
     * 这种方式确保了每个账户ID都有一个唯一的锁对象,而且这个过程是线程安全的。
     * @param accountId 账户ID
     * @return
     */
    private static Object getLock(String accountId) {
        // 如果不存在则添加
        lockMap.putIfAbsent(accountId, new Object());
        // 如果存在则返回
        return lockMap.get(accountId);
    }

    @Override
    public void run() {
        synchronized (getLock(this.accountId)) {
            updateBalance(accountId, amount);
        }
    }
}

线程池模拟

    public static void main(String[] args) {
        // 两个线程对同一个账户取款
        ATMTask task1 = new ATMTask("1", 800);
        ATMTask task2 = new ATMTask("1", 800);
        ATMTask task3 = new ATMTask("2", 700);
        ATMTask task4 = new ATMTask("2", 300);
        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(2);
        // 提交任务
        executor.submit(task1);
        executor.submit(task2);
        executor.submit(task3);
        executor.submit(task4);
        // 关闭线程池
        executor.shutdown();
    }

结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/787988.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024 WAIC|第四范式签约上海徐汇 加速推动“人工智能+千行百业”

7月5日&#xff0c;在“加速‘人工智能’构筑新质生产力”活动上&#xff0c;上海市徐汇区与作为大模型开发应用的核心企业第四范式举行签约仪式。徐汇区委常委、副区长俞林伟&#xff0c;第四范式联合创始人、总裁胡时伟等代表上台签约。 未来&#xff0c;双方将围绕人工智能前…

网络服务器配置与管理

网络服务器配置与管理是一个涉及多个方面的领域&#xff0c;它涵盖了从物理硬件的设置到操作系统、网络服务和应用的配置&#xff0c;再到日常维护和安全策略的实施。以下是网络服务器配置与管理的一些核心概念和步骤&#xff1a; 硬件配置&#xff1a; 选择合适的服务器硬件&a…

【多线程】wait()和notify()

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 为什么需要wait()方法和notify()方法&#xff1f;2. wait()方法2.1 wait()方法的作用2.2 wait()做的事情2…

IDEA新建项目并撰写Java代码的方法

本文介绍在IntelliJ IDEA软件中&#xff0c;新建项目或打开已有项目&#xff0c;并撰写Java代码的具体方法&#xff1b;Groovy等语言的代码也可以基于这种方法来撰写。 在之前的文章IntelliJ IDEA社区版在Windows电脑中的下载、安装方法&#xff08;https://blog.csdn.net/zheb…

01 | 基础架构:一条SQL查询语句是如何执行的?

此系列文章为极客时间课程《MySQL 实战 45 讲》的学习笔记&#xff01; 引言 在了解 SQL 查询语句如何执行之前&#xff0c;先了解下MySQL 的基本架构示意图。 MySQL 分为 Server 层和引擎层。 Server 层包括连接器、查询缓存、分析器、优化器、执行器等&#xff0c;涵盖 M…

揭秘GPT-4o:未来智能的曙光

引言 近年来&#xff0c;人工智能&#xff08;AI&#xff09;的发展突飞猛进&#xff0c;尤其是自然语言处理&#xff08;NLP&#xff09;领域的进步&#xff0c;更是引人注目。在这一背景下&#xff0c;OpenAI发布的GPT系列模型成为了焦点。本文将详细探讨最新的模型GPT-4o&a…

【刷题汇总 -- 求最小公倍数、数组中的最长连续子序列、字母收集】

C日常刷题积累 今日刷题汇总 - day0081、求最小公倍数1.1、题目1.2、思路1.3、程序实现 -- 穷举法1.2、程序实现 -- 辗转相除法 2、数组中的最长连续子序列2.1、题目2.2、思路2.3、程序实现 3、字母收集3.1、题目3.2、思路3.3、程序实现 4、题目链接 今日刷题汇总 - day008 1、…

基于STM32的智能加湿器

1.简介 基于STM32的加湿器发展前景非常乐观&#xff0c;这主要得益于其在技术、市场需求、应用场景以及政策支持等多方面的优势。STM32微控制器具备强大的处理能力和丰富的外设接口&#xff0c;能够实现精确的湿度监测和智能化控制。基于STM32的加湿器可以根据环境湿度自动调节…

Spark实现电商消费者画像案例

作者/朱季谦 故事得从这一张图开始说起—— 可怜的打工人准备下班时&#xff0c;突然收到领导发来的一份电商消费者样本数据&#xff0c;数据内容是这样的—— 消费者姓名&#xff5c;年龄&#xff5c;性别&#xff5c;薪资&#xff5c;消费偏好&#xff5c;消费领域&#x…

使用各向异性滤波器和图像处理方法进行脑肿瘤检测(MATLAB)

医学图像分割一直以来都是计算机辅助诊断领域的研究热点。在医学图像的处理和分析中&#xff0c;对图像中感兴趣区域的准确分割尤其关键。要对感兴趣区域进行分类识别&#xff0c;首先要从图像中把感兴趣区域精确分割出来&#xff0c;然后有针对性地对感兴趣区域提取特征并分类…

使用clion刷leetcode

如何优雅的使用clion刷leetcode 安装插件&#xff1a;LeetCode Editor) 插件配置&#xff1a; 这样我们每打开一个项目&#xff0c;就会创建类似的文件 我们的项目结构&#xff1a; 我们在题解文件中导入头文件myHeader.h并将新建的文件添加到cmakelists.txt文件&#xff0c;…

初识CPlusPlus

前言 也是好久没写博客了&#xff0c;那些天也没闲着&#xff0c;去练题去了。实际上练题也可以写练题的博客&#xff0c;但是觉得太简单了些&#xff0c;于是就没有继续写下去。如今又回来写博客&#xff0c;是因为有整理了新的知识C。内容不算多&#xff0c;大多数都是书本上…

接口测试工具Apifox使用以及多环境的配置

下载 Apifox - API 文档、调试、Mock、测试一体化协作平台 - 接口文档工具&#xff0c;接口自动化测试工具&#xff0c;接口Mock工具&#xff0c;API文档工具&#xff0c;API Mock工具&#xff0c;API自动化测试工具 安装 正常安装 , 微信扫码注册 apifox中创建项目 安装idea插…

数学建模美赛入门

数学建模需要的学科知识 高等数学线性代数 有很多算法的掌握是需要高等数学和线代的相关知识 如&#xff1a;灰色预测模型需要微积分知识&#xff1b;神经网络需要用到导数知识&#xff1b;图论和层次分析法等都需要用到矩阵计算的相关知识等&#xff1b; 概率论与数理统计&am…

Xubuntu24.04之设置高性能模式两种方式(二百六十一)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+AOSP…

YOLOv8改进 在通道维度上引入注意力机制CPCAttention

一、CPCAttention论文 论文地址:2306.05196 (arxiv.org) 二、CPCAttention结构 Channel prior convolutional attention (CPCA)用于图像分类和目标检测任务中。CPCA能够在卷积神经网络中引入通道相关性,并通过自适应地学习到每个通道的权重,从而提升模型的性能。 CPCA的关…

纯前端如何实现Gif暂停、倍速播放

前言 GIF 我相信大家都不会陌生&#xff0c;由于它被广泛的支持&#xff0c;所以我们一般用它来做一些简单的动画效果。一般就是设计师弄好了之后&#xff0c;把文件发给我们。然后我们就直接这样使用&#xff1a; <img src"xxx.gif"/>这样就能播放一个 GIF …

通过rpmbuild构建Elasticsearch-7.14.2-search-guard的RPM包

系列文章目录 rpmbuild从入门到放弃 search-guard插件使用入门手册 文章目录 系列文章目录前言一、资源准备二、spec文件1.基础信息2.%prep3.%Install4.%file5.%post6.%postun 三、成果演示1.执行构建过程图示例2.执行安装RPM包示例3.进程检查4.访问esApi 总结 前言 不管是源…

Linux--深入理与解linux文件系统与日志文件分析

一、文件与存储系统的 inode 与 block 1.1 硬盘存储 最小存储单位:扇区( sector )每个扇区存储大小:512 字节1.2 文件存取--block block(块),每个 block 块大小为:4k由连续的八个扇区组成一个 block 块是文件索引最小的单位每个 block 块中包括:文件数据文件数据:就…

LeetCode(2)-反转链表、删除链表中等于val的节点、返回链表中的中间节点

一、反转链表 . - 力扣&#xff08;LeetCode&#xff09; 解法1&#xff1a; /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/ typedef struct ListNode ListNode; struct ListNode* reverseList(struct ListN…