java多线程-练习

需求

在这里插入图片描述

代码

  • 使用Callable 方便返回执行的结果:每个线程的发送礼物的数量
  • 礼物清单:共享资源,方便上锁
  • 礼物数量:线程变量,每个线程发送礼物的数量
public class SendGiftThread implements Callable<Integer> {

    // 共享资源 礼物清单
    private ArrayList<String> giftList;
    // 此线程已经送出的礼物数量
    private int count = 0;

    public SendGiftThread(ArrayList<String> giftList) {
        this.giftList = giftList;
    }

    public int getCount() {
        return count;
    }


    @Override
    public Integer call() throws Exception {
        Random random = new Random();
        while (giftList.size() > 10){
            // 锁住的不一定是this,一定要是共享资源
            synchronized (giftList){
                // 礼物大于10个时,随机送出一个礼物
                if (giftList.size() > 10){
                    int index = random.nextInt(giftList.size());
                    // 送出礼物
                    String remove = giftList.remove(index);
                    // 送出礼物数量+1
                    count++;
                    System.out.println(Thread.currentThread().getName() + "送出了" + remove + ",已送出" + count + "个礼物");
                }
            }
        }
        return count;
    }
}
  • 创建两个Callable对象
  • 使用未来任务FutureTask进行封装
  • 创建两个线程
public static void main(String[] args) {
    // 随机生成100个礼物
    ArrayList<String> giftList = new ArrayList<>();
    String[] names = {"口红", "手机", "电脑", "手表", "鞋子", "衣服", "裤子", "帽子", "围巾", "手套", "袜子", "饰品", "包包", "眼镜", "钱包", "皮带", "项链", "手链", "戒指", "耳环"};
    Random random = new Random();
    for (int i = 0; i < 100; i++) {
        giftList.add(names[random.nextInt(names.length)]+"-"+i);
    }

    // 创建两个任务
    SendGiftThread sendGiftThread1 = new SendGiftThread(giftList);
    SendGiftThread sendGiftThread2 = new SendGiftThread(giftList);
    Future<Integer> future1 = new FutureTask<>(sendGiftThread1);
    Future<Integer> future2 = new FutureTask<>(sendGiftThread2);
    // 创建两个线程
    Thread thread1 = new Thread((Runnable) future1, "小红");
    Thread thread2 = new Thread((Runnable) future2, "小明");
    // 启动线程
    thread1.start();
    thread2.start();

    // 打印线程返回结果
    try {
        System.out.println("小红送出了" + future1.get() + "个礼物");
        System.out.println("小明送出了" + future2.get() + "个礼物");
    } catch (Exception e) {
        e.printStackTrace();
    }



}

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

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

相关文章

通过命令行构建Django应用程序

假设读者安装好Django开发环境后&#xff08;这个环境搭建很容易&#xff0c;大家可以参看随意一个网文&#xff09;&#xff0c;就可以通过命令行构建Django应用程序了。通过命令行构建Django应用程序的关键&#xff0c;是使用一个Django框架自带的管理工具——django-admin.p…

springboot3 集成knife4j

knife4j介绍 Knife4j是一个集Swagger2 和 OpenAPI3为一体的增强解决方案。 springdoc地址&#xff1a;OpenAPI 3 Library for spring-boot Knife4j官网地址&#xff1a;Knife4j 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j 环境介绍 java&#xff1a;17 Spring…

你们项目日志是如何处理的???

ELK日志采集系统 1.什么是ELK ELK 是一套流行的数据搜索、分析和可视化解决方案&#xff0c;由三个开源项目组成&#xff0c;每个项目的首字母合起来形成了“ELK”这一术语&#xff1a; Elasticsearch (ES): Elasticsearch 是一个基于 Apache Lucene 构建的分布式、实时搜索与…

项目开发流程

项目开发流程 &#x1f469;‍&#x1f9b3;项目立项 估计项目的花费&#xff0c;确定大致的所需开发人员数&#xff0c;确定项目是否可行&#xff1b; &#x1f469;‍&#x1f9b0;需求分析 整体过程&#xff1a; 项目背景和目标&#xff0c;即项目的目的是什么 用户需求&…

动态Web项目讲解+Demo

web流程演示 请求路径 请求路径明确要请求的是哪个servlet 请求方式 servlet含有两种请求方式&#xff1a;doGet和doPost doGet&doPost 返回数据就是httpResponse&#xff0c;返回给success 参数 包含在request当中 成功 上述流程任何一步都没出问题&#xff0c;就会…

设计模式之创建型模式---工厂模式

文章目录 工厂模式概述简单工厂简单工厂的代码实现简单工厂的使用简单工厂应用场景 工厂方法工厂方法模式的代码实现工厂方法的使用工厂方法应用场景 抽象工厂抽象工厂模式代码实现抽象工厂的使用方法抽象工厂模式的应用场景 总结 工厂模式概述 工厂模式从名字就能看出&#x…

在【laravel框架】学习中遇到的常见的问题以及解决方法

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

.net core webapi 高颜值的接口管理系统界面取代swagger,更好调试和查看

.net core webapi 高颜值的接口管理系统界面取代swagger&#xff0c;更好调试和查看 安装 dotnet add package IGeekFan.AspNetCore.Knife4jUI --version 0.0.16配置文档&#xff1a; 配置起始页 builder.Services.AddSwaggerGen(c > {// 配置 Swagger 文档相关信息c.Swa…

开源项目实现简单实用的股票回测

1 引言 之前&#xff0c;尝试做股票工具一直想做的大而全&#xff0c;试图抓取长期的各个维度数据&#xff0c;然后统计或者训练模型。想把每个细节做到完美&#xff0c;结果却陷入了细节之中&#xff0c;最后烂尾了。 最近&#xff0c;听到大家分享了一些关于深度学习、时序…

【面试题】MySQL 事务的四大特性说一下?

事务是一个或多个 SQL 语句组成的一个执行单元&#xff0c;这些 SQL 语句要么全部执行成功&#xff0c;要么全部不执行&#xff0c;不会出现部分执行的情况。事务是数据库管理系统执行过程中的一个逻辑单位&#xff0c;由一个有限的数据库操作序列构成。 事务的主要作用是保证数…

Core dump(核心转储)

文章目录 core dump core dump 进程退出时有三种情况正常退出&#xff0c;退出结果不对&#xff0c;异常退出 低7位表示收到信号退出&#xff0c;次低八位代表进程正常退出它的退出码&#xff01;在第八位有一个core dump标志位&#xff0c;这个标志位表示进程收到信号做的动…

Leetcode 28. 找出字符串中第一个匹配项的下标

心路历程&#xff1a; 两个字符串匹配的问题基本都可以用动态规划解决&#xff0c;递推关系就是依次匹配下去 注意的点&#xff1a; 1、注意边界条件是匹配串needle到头&#xff0c;但是haystack不一定需要到头 2、这道题按照从i开始的字符串而不是从i结束的进行DP建模 解法…

vue---计算属性

姓名案例 1.使用插值语法实现 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>姓名案例_插值语法实现</title><!-- 引入Vue --><script type"text/javascript" src"../js/vue.js"&g…

被这批B端界面的颜值给征服了,匍匐拜倒。。

高颜值的 B 端界面对于企业来说具有非常重要的作用&#xff0c;可以帮助企业提升品牌形象、吸引客户、增加用户留存、提升竞争力、提高交易转化率&#xff0c;以及优化用户体验&#xff0c;从而为企业带来更多的商业机会和利益。本期分享一批&#xff0c;都是颜值杠杠的。

制造业信息安全实践——企业信息安全运营规划

前言 制造业作为一个庞大的传统产业&#xff0c;涵盖了汽车、船舶、飞机、家电、新能源等众多领域。当前&#xff0c;无论是国内还是国外的制造业都面临着一个共同的挑战&#xff1a;在计算机和信息时代的背景下&#xff0c;如何跟上IT技术的发展步伐&#xff1f;如何让传统产…

网络协议安全:OSI七层模型分层及作用,数据封装与解封过程,数据传输过程。

「作者简介」&#xff1a;2022年北京冬奥会中国代表队&#xff0c;CSDN Top100&#xff0c;学习更多干货&#xff0c;请关注专栏《网络安全自学教程》 这一章节我们需要知道OSI分哪七层&#xff0c;每层的作用&#xff0c;知道数据在七层模型中是怎样传输的&#xff0c;封包和解…

【离婚不再难】告别痛苦,用一纸起诉状重新启航

【离婚不再难】告别痛苦&#xff0c;用一纸起诉状重新启航 在这个瞬息万变的时代&#xff0c;婚姻关系的走向已不再是人们心中永恒的定局。当缘尽人散&#xff0c;面对离婚的纷扰&#xff0c;你是否感到迷茫与无助&#xff1f;别担心&#xff0c;李秘书讲写作公众号在这里&…

C++11——线程库的理解与使用

目录 前言 一、线程库的构造 1.默认构造 2.带参构造 3.拷贝构造与赋值拷贝&#xff08;不支持&#xff09; 4.移动构造 二、线程调用lambda函数 三、线程安全与锁 1.lambda中的线程与锁 2.函数指针中的线程与锁 3.trylock() 4.recursive_mutex 5.lock_gurad守卫锁…

​「Python大数据」VOC数据清洗

前言 本文主要介绍通过python实现数据清洗、脚本开发、办公自动化。读取voc数据,存储新清洗后的voc数据数据。 一、业务逻辑 读取voc数据采集的数据批处理,使用jieba进行分词,去除停用词,清洗后的评论存储到新的列中保存清洗后的数据到新的Excel文件中二、具体产出 三、执…

three.js(2):渲染第一个three.js三维对象

这一章渲染一个立方体对象到场景中&#xff0c;效果如下&#xff1a; 代码如下&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><script text"module" charset"UTF-8"…