Java多线程,实现卖电影票的业务
本篇重点:多线程共享资源时发生的互斥问题
一般的我们售卖电影票或者火车票时会有多个窗口同时买票,
我们来看测试代码:主方法new一个Ticket(一个堆),之后三个线程来启动(三个窗口买票)
class Ticket implements Runnable{
private static int ticket=10;
@Override
public void run() {
for(int i=1;i<=100;i++){
System.out.println(Thread.currentThread().getName()+" - 开始买票");
synchronized(this){ //同步代码块+对象锁
System.out.println(Thread.currentThread().getName()+" - 买了第"+ticket+"张票");
ticket--;
}
System.out.println(Thread.currentThread().getName()+" - 结束买票");
if(ticket<=0){break;}
}
}
}
public class Demo {
public static void main(String[] args) {
Ticket ticket=new Ticket();
new Thread(ticket,"1号窗口").start();
new Thread(ticket,"2号窗口").start();
new Thread(ticket,"3号窗口").start();
}
}
同步块内的代码是原子性的,在没有执行完所有语句时是不会出让CPU的。
在分析以上代码前,我们先简化模型。
class Ticket implements Runnable{
@Override
public void run() {
for(int i=1;i<=5;i++){
System.out.println(Thread.currentThread().getName()+" - A");
System.out.println(Thread.currentThread().getName()+" - B");
System.out.println(Thread.currentThread().getName()+" - C");
}
}
}
public class Demo {
public static void main(String[] args) {
Ticket ticket=new Ticket();
new Thread(ticket,"t1").start();
new Thread(ticket,"t2").start();
new Thread(ticket,"t3").start();
}
}
运行如图:
t1 - A
t2 - A
t3 - A
t3 - B
t1 - B
t3 - C
t2 - B
t2 - C
t3 - A
t1 - C
t1 - A
t1 - B
t1 - C
t3 - B
t3 - C
t3 - A
t2 - A
t3 - B
t1 - A
t3 - C
t2 - B
t3 - A
t1 - B
t3 - B
t2 - C
t3 - C
t1 - C
t3 - A
t2 - A
t2 - B
t2 - C
t2 - A
t2 - B
t2 - C
t2 - A
t2 - B
t3 - B
t1 - A
t3 - C
t2 - C
t1 - B
t1 - C
t1 - A
t1 - B
t1 - C
每次运行结果都会不一样,因为轮流抢占CPU不是我们能控制的。
图解分析:

由分析我们得出大概是以一条语句作为基本单位来执行,若多条语句需要作为一个原子性的整理,就需要加互斥锁。
原理大致如图:

加锁的这段区域被称为“互斥区”,里面的代码必须整理执行完毕才会释放锁,让其他线程切入进来。
synchronized具有加锁的功能,实现比较简单。
我们再看卖票的代码:
class Ticket implements Runnable{
private static int ticket=10;
@Override
public void run() {
for(int i=1;i<=100;i++){
try {
Thread.sleep(500); //线程休眠500毫秒,以便观察输出
} catch (InterruptedException e) { //需要处理异常
e.printStackTrace();
}
synchronized(this){ //同步代码块+对象锁(this表示对象锁)
if(ticket<=0){break;}
System.out.println(Thread.currentThread().getName()+" 买了第"+ticket+"张票");
ticket--;
}
}
}
}
public class Demo {
public static void main(String[] args) {
Ticket ticket=new Ticket();
new Thread(ticket,"1号窗口").start();
new Thread(ticket,"2号窗口").start();
new Thread(ticket,"3号窗口").start();
}
}
运行如图:

Java多线程,实现卖电影票的业务的更多相关文章
- java多线程实现卖票小程序
package shb.java.demo; /** * 多线程测试卖票小程序. * @Package:shb.java.demo * @Description: * @author shaobn * ...
- java 多线程之卖票两种方式
1.通过extends Thread /* 需求:简单的卖票,多个窗口同时买票 (共用资源) 创建线程的第二种方式:实现Runnable接口 步骤: 1,定义类实现Runnable接口 2,覆盖/重写 ...
- Java 多线程:什么是线程安全性
线程安全性 什么是线程安全性 <Java Concurrency In Practice>一书的作者 Brian Goetz 是这样描述"线程安全"的:"当多 ...
- Java多线程简析
一.线程的状态: 线程共有下面4种状态: 1.新建状态(New): 新创建了一个线程对象,当你用new创建一个线程时,该线程尚未运行. 2.就绪状态(Runnable): 线程对象创建后,其他线程调用 ...
- Java 多线程——基础知识
java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...
- ***Java多线程发展简史
http://blog.jobbole.com/28297/ 本文来自四火的博客(@RayChase),由@_Zhijun 推荐 这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的 ...
- [转] Java多线程发展简史
这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的Knowledge Sharing的一个整理,我希望能对Java从第一个版本开始,在多线程编程方面的大事件和发展脉络有一个描述,并 ...
- 【52】java多线程剖析
线程的状态: 线程共有下面4种状态: 新建状态(New): 新创建了一个线程对象,当你用new创建一个线程时,该线程尚未运行. 就绪状态(Runnable): 线程对象创建后,其他线程调用了该对象的s ...
- Java多线程、线程池和线程安全整理
多线程 1.1 多线程介绍 进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 1.2 Thread类 通 ...
随机推荐
- dataTables使用的详细说明整理
本文共三个部分:官网|基本使用|遇到的问题 一.官方网站:http://www.datatables.club/ 二.基本使用: 1.dataTables的引入及初始化 <!--第一步:引入Ja ...
- Ansible--常用命令整理
由于最近使用ansible在多台服务器部署程序,运行命令的时候,发现对Linux和ansible自动运维工具用的不太熟练,所以搜集整理一些,方便日后复习提升,达到熟练运用的目的. 对于详细的安装教程和 ...
- PHP foreach &$ 引发的bug
在使用foreach &$来更新数据的时候,造成数据被更新掉了 $arr = array(1,2,3,4,5); foreach ($arr as &$row) { $row += 1 ...
- Hadoop运行模式:本地模式、伪分布模式、完全分布模式
1.本地模式:默认模式 - 不对配置文件进行修改. - 使用本地文件系统,而不是分布式文件系统. - Hadoop不会启动NameNode.DataNode.ResourceManager.NodeM ...
- Leading and Trailing LightOJ - 1282 题解
LightOJ - 1282 Leading and Trailing 题解 纵有疾风起 题目大意 题意:给你一个数n,让你求这个数的k次方的前三位和最后三位. \(2<=n<2^{31} ...
- 一个阿里云apache服务器配置两个或多个域名forLinux
一个阿里云apache服务器配置两个或多个域名for Linux: 默认已经配置好了阿里云提供的一键web安装,可以参考:http://www.42iot.com/?id=8 修改/alidata/s ...
- A.Gennady and a Card Game
http://m3.codeforces.com/contest/1097/problem/A Gennady and a Card Game time limit per test 1 second ...
- sql基本语法大全
一.定义变量--简单赋值 declare @a intset @a=5 print @a --使用select语句赋值 declare @user1 nvarchar(50) select @user ...
- echart 属性设计大全
// 全图默认背景 // backgroundColor: ‘rgba(0,0,0,0)’, // 默认色板 color: ['#ff7f50','#87cefa','#da70d6','#32cd ...
- vue.js(10)--案例--列表增加与删除
品牌管理案例 (1)bootstrip快速布局 <div class="app"> <div class="panel panel-primary&qu ...