Java 多线程卖票
来源:互联网 发布:淘宝宝贝图片宽度 编辑:程序博客网 时间:2024/05/17 06:13
在实际应用中,我们经常用到多线程,如车站的售票系统,车站的各个售票口相当于各个线程。当我们做这个系统的时候可能会想到两种方式来实现,继承Thread类或实现Runnable接口,现在看一下这两种方式实现的两种结果。
继承Thread类:
class MyThread extends Thread { private int ticket = 5; private String name; public MyThread(String name) { this.name = name; } public void run() { //for监控每个窗口卖票的张数,必须有,不然只买1张就结束 for (int i = 0; i < 500; i++) { if (this.ticket > 0) { System.out.println(this.name + "第"+i+"次卖票---->" + (this.ticket--)); } } }}public class TicketsThread { public static void main(String[] args) { //创建三个线程,模拟三个窗口卖票 MyThread mt1 = new MyThread("一号窗口"); MyThread mt2 = new MyThread("二号窗口"); MyThread mt3 = new MyThread("三号窗口"); //启动这三个线程,即窗口,开始卖票 mt1.start(); mt2.start(); mt3.start(); }}
运行结果:
继承Thread类的,我们相当于拿出三件事即三个卖票5张的任务分别分给三个窗口,他们各做各的事各卖各的票各完成各的任务,因为MyThread继承Thread类,所以在new MyThread的时候在创建三个对象的同时创建了三个线程;
实现Runable方法
class MyThread1 implements Runnable{ private int ticket =10; private String name; public void run(){ for(int i =0;i<500;i++){ if(this.ticket>0){ System.out.println(Thread.currentThread().getName()+"第"+i+"次"+"卖票---->"+(this.ticket--)); } } }}public class TicketsRunable { public static void main(String[] args) { // TODO Auto-generated method stub //设计三个线程 MyThread1 mt = new MyThread1(); Thread t1 = new Thread(mt,"一号窗口"); Thread t2 = new Thread(mt,"二号窗口"); Thread t3 = new Thread(mt,"三号窗口");// MyThread1 mt2 = new MyThread1();// MyThread1 mt3 = new MyThread1(); t1.start(); t2.start(); t3.start(); }}
运行结果
实现Runnable的, 相当于是拿出一个卖票10张得任务给三个人去共同完成,new MyThread1相当于创建一个任务,然后实例化三个Thread,创建三个线程即安排三个窗口去执行。
线程安全
上面的两种方式是实现多线程的基本方式,但是在运行的时候有的时候发现同一张票会卖2次,线程不安全,数据未同步。
synchronized
public void run() { while (this.ticket > 0) { synchronized (this) { System.out.println(Thread.currentThread().getName() + "第" + "次" + "卖票---->" + (this.ticket--)); } } }
多次跑会出现这种情况,还是线程不安全,思考一下,如果2 3窗口在还有1张被锁住,等待完资源,此时数据已经脏了。
this.ticket这部操作,将ticket从主内存读取到工作内存,2号 3号同时读取了2个副本,因此可能出现不安全情况。
class MyThread1 implements Runnable { private int ticket = 20; private String name; public void run() { while (true) { synchronized (this) { if (this.ticket > 0) { System.out.println(Thread.currentThread().getName() + "第" + "次" + "卖票---->" + (this.ticket--)); } } } }}
线程安全,数据正常。
1. 获得同步锁;
2. 清空工作内存;
3. 从主内存拷贝对象副本到工作内存;this.ticket到工作内存
4. 执行代码(计算或者输出等);
5. 刷新主内存数据;
6. 释放同步锁。
所以使用synchronized ,锁的位置很重要!!!
volatile
class MyThread1 implements Runnable{ private volatile int ticket =20; private String name; public void run(){ while (this.ticket>0){ System.out.println(Thread.currentThread().getName()+"第"+"次"+"卖票---->"+(this.ticket--)); } }}
线程安全,数据正常。volatile
1. 将变量i从主内存拷贝到工作内存;
2. 改变i的值;
3. 刷新主内存数据;
4. 将变量j从主内存拷贝到工作内存;
5. 改变j的值;
6. 刷新主内存数据;
参考:
http://mars914.iteye.com/blog/1508429
http://blog.csdn.net/mccand1234/article/details/52130271
- Java 多线程卖票演示
- Java多线程-卖票
- Java 多线程卖票
- java多线程卖票问题。
- Java 多线程卖票例子
- JAVA多线程实现模拟卖票
- java多线程:6、模拟卖票
- Java多线程实例之卖票
- 多线程卖票
- 【java】多线程小例子(卖票示例)
- Java多线程—两种卖票
- java多线程重复卖票的问题
- Java---12---多线程练习:卖票---实现数据共享
- Java 多线程实现多个窗口同时卖票
- java多线程卖票-教你简单易懂三步骤
- java实现多线程卖票(重点分析Thread.sleep())
- Java多线程之并发安全经典案例-卖票
- Java多线程通信、同步卖票实例--线程安全、详细注释
- Fragment生命周期
- http://www.cnblogs.com/EricaMIN1987_IT/p/3837436.html
- KindEditor的使用和注意事项
- 数据库的学习笔记
- 排序算法的思考和总结(一)-冒泡和选择排序
- Java 多线程卖票
- Maven报错: Could not resolve archetype org.apache.maven.archetypes:maven-archetype-webapp
- Moto Z Force拍照性能得到87分,DxOMark惹争议
- php 编写一个简单的模板引擎
- 设置套接字选项值setsockopt()函数使用详解
- 远程重启服务器
- python 正则表达式 之re.findall
- HDOJ-2124之Repair the Wall
- 微信刮刮乐