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

相关文章

【区块链 + 人才服务】可信教育区块链治理系统 | 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

Java 多线程概述

多线程技术概述   1.线程与进程 进程:内存中运行的应用程序,每个进程都拥有一个独立的内存空间。线程:是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换、并发执行,一个进程最少有一个线程,线程实际数是在进程基础之上的进一步划分,一个进程启动之后,进程之中的若干执行路径又可以划分成若干个线程 2.线程的调度 分时调度:所有线程轮流使用CPU的使用权,平均分配时间抢占式调度

Java 多线程的基本方式

Java 多线程的基本方式 基础实现两种方式: 通过实现Callable 接口方式(可得到返回值):

基于SpringBoot的宠物服务系统+uniapp小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统+原生微信小程序+LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统+LW参考示例 3.基于SpringBoot+Vue的企业人事管理系统+LW参考示例 4.基于SSM的高校实验室管理系统+LW参考示例 5.基于SpringBoot的二手数码回收系统+原生微信小程序+LW参考示例 6.基于SSM的民宿预订管理系统+LW参考示例 7.基于

java线程深度解析(六)——线程池技术

http://blog.csdn.net/Daybreak1209/article/details/51382604 一种最为简单的线程创建和回收的方法: [html]  view plain copy new Thread(new Runnable(){                @Override               public voi

java线程深度解析(五)——并发模型(生产者-消费者)

http://blog.csdn.net/Daybreak1209/article/details/51378055 三、生产者-消费者模式     在经典的多线程模式中,生产者-消费者为多线程间协作提供了良好的解决方案。基本原理是两类线程,即若干个生产者和若干个消费者,生产者负责提交用户请求任务(到内存缓冲区),消费者线程负责处理任务(从内存缓冲区中取任务进行处理),两类线程之