Thread线程二 多线程服务 卖票服务

2024-03-14 09:08

本文主要是介绍Thread线程二 多线程服务 卖票服务,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

卖票服务

引入问题:
有一百张票,分为三个从窗口

测试类

public static void main(String[] args) {RunnableImpl run=new RunnableImpl();Thread t0=new Thread(run);Thread t1=new Thread(run);Thread t2=new Thread(run);//调用start,开启多线程t0.start();t1.start();t2.start();
}

第一次代码:

只要有票就售出,三个窗口为三个线程,同时执行

public class RunnableImpl implements Runnable {
private int ticket=100;
@Override
public void run() {while (true){if(ticket>0){System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");ticket--;}}}
}

效果:
Thread-2正在卖第100张票!
Thread-2正在卖第99张票!
Thread-2正在卖第98张票!
Thread-1正在卖第100张票!
Thread-1正在卖第96张票!
Thread-2正在卖第97张票!
Thread-2正在卖第94张票!
Thread-2正在卖第93张票!
Thread-0正在卖第100张票!
原因:线程争夺资源,同时进入cpu中,系统没有调休实现,所以出现票重复 卖出的情况。

改进算法:

卖票的时间每个改为10ms,意味着线程休眠10ms。使得资源得以缓冲
static void sleep(long millis)
使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。

public class RunnableImpl implements Runnable {
private int ticket=100;
@Override
public void run() {while (true){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}if(ticket>0){System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");ticket--;}}}
}

效果:
Thread-0正在卖第100张票!
Thread-1正在卖第100张票!
Thread-2正在卖第100张票!
Thread-0正在卖第97张票!
Thread-1正在卖第97张票!
Thread-2正在卖第95张票!
原因:还是因为争夺cpu,同时进入,改进并没有找到根本原因!
在这里插入图片描述

使用synchronized(锁对象)同步代码块

synchronized(锁对象)
{可能会出现线程安全问题的代码(访问了共享数据的代码)}
注意:

  • 1.通过代码块中的锁对象,可以使用任意的对象

  • 2.但是必须保证多个线程使用的锁对象是同一个

  • 3.锁对象作用:

  • 把同步代码块锁住,只让一个线程在同步代码块中执行

      public class RunnableImpl implements Runnable {private  int ticket=100;//创建一个锁对象
    Object obj=new Object();
    @Overridepublic void run() {while (true){//同步代码块synchronized (obj)//也可以synchronized(this){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}if(ticket>0){System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");ticket--;}}}}}
    

    效果:
    Thread-0正在卖第100张票!
    Thread-0正在卖第99张票!
    Thread-0正在卖第98张票!
    Thread-0正在卖第97张票!
    Thread-0正在卖第96张票!
    Thread-0正在卖第95张票!
    Thread-0正在卖第94张票!
    Thread-0正在卖第93张票!
    原理:
    在这里插入图片描述

使用同步方法

锁对象是this
使用步骤:
1.把访问了共享数据代码抽取出来,放入到一个方法中
2.在方法上添加synchronized
代码:

public class RunnableImpl implements Runnable {
private int ticket=100;
//创建一个锁对象
@Override
public void run() {while (true){//同步代码块payTicket();}}
public synchronized void payTicket()
{if(ticket>0){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");ticket--;}
}
}

效果:
Thread-0正在卖第100张票!
Thread-0正在卖第99张票!
Thread-0正在卖第98张票!
Thread-0正在卖第97张票!
Thread-0正在卖第96张票!
Thread-0正在卖第95张票!
Thread-0正在卖第94张票!
Thread-0正在卖第93张票!
设置票为私有静态,则同步方法也是静态方法
静态的同步方法
锁对象是静态方法的锁对象是本类的class属性–>class文件对象(反射

代码:

public class RunnableImpl implements Runnable {
private static int ticket=100;//创建一个锁对象
@Override
public void run() {while (true){//同步代码块payTicket();}}
/*使用静态方法解决同步问题*/
public static synchronized void payTicket()
{//去掉synchronized 关键字换上//synchronized(RunnableImpl.class){}if(ticket>0){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在卖第"+ticket+"张票!");ticket--;}
}
}

这篇关于Thread线程二 多线程服务 卖票服务的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/807920

相关文章

windos server2022的配置故障转移服务的图文教程

《windosserver2022的配置故障转移服务的图文教程》本文主要介绍了windosserver2022的配置故障转移服务的图文教程,以确保服务和应用程序的连续性和可用性,文中通过图文介绍的非... 目录准备环境:步骤故障转移群集是 Windows Server 2022 中提供的一种功能,用于在多个

解决systemctl reload nginx重启Nginx服务报错:Job for nginx.service invalid问题

《解决systemctlreloadnginx重启Nginx服务报错:Jobfornginx.serviceinvalid问题》文章描述了通过`systemctlstatusnginx.se... 目录systemctl reload nginx重启Nginx服务报错:Job for nginx.javas

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

Java子线程无法获取Attributes的解决方法(最新推荐)

《Java子线程无法获取Attributes的解决方法(最新推荐)》在Java多线程编程中,子线程无法直接获取主线程设置的Attributes是一个常见问题,本文探讨了这一问题的原因,并提供了两种解决... 目录一、问题原因二、解决方案1. 直接传递数据2. 使用ThreadLocal(适用于线程独立数据)

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

Thread如何划分为Warp?

1 .Thread如何划分为Warp? https://jielahou.com/code/cuda/thread-to-warp.html  Thread Index和Thread ID之间有什么关系呢?(线程架构参考这里:CUDA C++ Programming Guide (nvidia.com)open in new window) 1维的Thread Index,其Thread

多线程解析报表

假如有这样一个需求,当我们需要解析一个Excel里多个sheet的数据时,可以考虑使用多线程,每个线程解析一个sheet里的数据,等到所有的sheet都解析完之后,程序需要提示解析完成。 Way1 join import java.time.LocalTime;public class Main {public static void main(String[] args) thro

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api