黑马程序员--第六篇 多线程之卖票案例
第六篇 多线程之卖票案例
只有练习,才能内化,下面是运用多线程原理实现的一个卖票程序系统。
要求是:三个窗口同时卖票,不能出现同票,负数票。我们选择Runnable接口的方式
/*
* 实现Runnable接口的方式实现
*
* 通过加入延迟后,就产生了连个问题:
* A:相同的票卖了多次
* CPU的一次操作必须是原子性的
* B:出现了负数票
* 随机性和延迟导致的
*/
class SellTicket implements Runnable {
// 定义100张票,让三个线程对象共享。
private static int tickets = 100;
// 定义同一把锁,保证每次只能有一个线程执行同步代码块。
private Object obj = new Object(); //不过此处的对象可以是任意的。
//同步代码块用obj做锁
@Override
public void run() {
while (true) {
synchronized (obj) {
if (tickets > 0) {
//此处需要处理异常,但是其父类都没有抛出异常,子类就只能Try..catch来处理。
try {
//为了模拟现实中售票会存在网络延迟。所以加入了睡眠100ms.
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()
+ "正在出售第" + (tickets--) + "张票 ");
}
}
}
}
// }
// }
public class SellTicketDemo {
public static void main(String[] args) {
// 创建资源对象
SellTicket st = new SellTicket();
// 创建三个线程对象
Thread t1 = new Thread(st, "窗口1");
Thread t2 = new Thread(st, "窗口2");
Thread t3 = new Thread(st, "窗口3");
// 启动线程
t1.start();
t2.start();
t3.start();
}
}
总结:1,电影院卖票程序可能出现的问题及解决。
卖票问题
a:同票多次
b:会出现负数票
2,多线程安全问题的原因(也是我们以后判断一个程序是否有线程安全问题的依据)
A:是否有多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
3,同步解决线程安全问题
A:同步代码块
synchronized(对象) {
需要被同步的代码;
}
这里的锁对象可以是任意对象。
注意:锁对象要能被所有线程对象共享,这样确保每次只有一个线程对象执行同步代码块。
B:同步方法
把同步加在方法上。
这里的锁对象是this
C:静态同步方法
把同步加在方法上。
这里的锁对象是当前类的字节码文件对象(反射再讲字节码文件对象)