本篇重点:多线程共享资源时发生的互斥问题

一般的我们售卖电影票或者火车票时会有多个窗口同时买票,

我们来看测试代码:主方法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多线程,实现卖电影票的业务的更多相关文章

  1. java多线程实现卖票小程序

    package shb.java.demo; /** * 多线程测试卖票小程序. * @Package:shb.java.demo * @Description: * @author shaobn * ...

  2. java 多线程之卖票两种方式

    1.通过extends Thread /* 需求:简单的卖票,多个窗口同时买票 (共用资源) 创建线程的第二种方式:实现Runnable接口 步骤: 1,定义类实现Runnable接口 2,覆盖/重写 ...

  3. Java 多线程:什么是线程安全性

    线程安全性 什么是线程安全性 <Java Concurrency In Practice>一书的作者 Brian Goetz 是这样描述"线程安全"的:"当多 ...

  4. Java多线程简析

    一.线程的状态: 线程共有下面4种状态: 1.新建状态(New): 新创建了一个线程对象,当你用new创建一个线程时,该线程尚未运行. 2.就绪状态(Runnable): 线程对象创建后,其他线程调用 ...

  5. Java 多线程——基础知识

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  6. ***Java多线程发展简史

    http://blog.jobbole.com/28297/ 本文来自四火的博客(@RayChase),由@_Zhijun 推荐 这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的 ...

  7. [转] Java多线程发展简史

    这篇文章,大部分内容,是周五我做的一个关于如何进行Java多线程编程的Knowledge Sharing的一个整理,我希望能对Java从第一个版本开始,在多线程编程方面的大事件和发展脉络有一个描述,并 ...

  8. 【52】java多线程剖析

    线程的状态: 线程共有下面4种状态: 新建状态(New): 新创建了一个线程对象,当你用new创建一个线程时,该线程尚未运行. 就绪状态(Runnable): 线程对象创建后,其他线程调用了该对象的s ...

  9. Java多线程、线程池和线程安全整理

    多线程 1.1      多线程介绍 进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 1.2      Thread类 通 ...

随机推荐

  1. python基础-8迭代器(iter)和生成器(yield)

    一 生成器 从Python2.2起,生成器提供了一种简洁的方式帮助返回列表元素的函数来完成简单和有效的代码. 它基于yield指令,允许停止函数并立即返回结果.此函数保存其执行上下文,如果需要,可立即 ...

  2. MongoDB 基本操作(增改删)

    1.插入数据 和关系型数据库一样,增加数据记录可以使用insert语句,这是很简单的. 当插入数据时,如果此集合不存在,则MongoDB系统会自动创建一个集合,即不需要刻意预先创建集合 每次插入数据时 ...

  3. Ubuntu 12.04安装Gitlab及问题解决

    最近看了下Git,并且之前听同学说过gitlab这个东西,就想自己也搭建一个gitlab,做一个像github那样的代码管理站点,现在的gitlab要安装确实是非常非常方便, https://abou ...

  4. Javascript 中的深浅拷贝

    工作中经常会遇到需要复制 JS 数据的时候,遇到 bug 时实在令人头疼:面试中也经常会被问到如何实现一个数据的深浅拷贝,但是你对其中的原理清晰吗?一起来看一下吧! 为什么会有深浅拷贝 想要更加透彻的 ...

  5. 打乱一个排好序的 list 对象 alist?

    1. import random 2. random.shuffle(alist)

  6. 如何将datetimepicker默认设置为空?

    在Load中,初始化 this.dateTimePicker1.Format=DateTimePickerFormat.Custom; his.dateTimePicker1.CustomFormat ...

  7. IIS是怎么处理多个请求的?

      一,假设有一台服务器,它的IIS上部署有一个Web应用程序-S,可以通过浏览器或其他方式进行访问.     假设有A.B.C三台电脑同时访问网站S,IIS接收到3个HTTP请求,然后分别为三个请求 ...

  8. 在a标签中使用了onclick修改样式之后a:hover失效

    是因为优先级的原因造成,使用!important修改优先级. 如修改成: .button1:hover {            color: #FFF !important;            ...

  9. fiddler 手机抓包,CS端抓包 使用记录

    1.允许远程连接 2.忽略https证书错误 3.设置代理 4.重启fiddle 5.PC客户端抓包分工具FIddler+Proxifer https://blog.csdn.net/sunbo_cs ...

  10. Linux shell中自动完成登录

    在写shell脚本时,需要登录到不同的服务器上执行相关命令,在未建立信任之前如何批量操作. 1.ssh 首次登录服务器时会提示RSA key fingerprint输入yes/no,可以通过下面的方法 ...