目录
案例:卖票
需求:某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票
思路:
1、定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:privateinttickets=100
2、在SellTicket类中重写run)方法实现卖票,代码步骤如下
A:判断票数大于0,就卖票,并告知是哪个窗口卖的B:卖了票之后,总票数要减1
C:票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行3、定义一个测试类SellTicketDemo,里面有main方法,代码步骤如下
A:创建SellTicket类的对象
B:创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称C:启动线程
package zyy04; public class Sell implements Runnable{ private int tickets=10; @Override public void run() { while (true) { if (tickets > 0) { System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票"); tickets--; } } } }
package zyy04; public class Demo { public static void main(String[] args) { Sell s=new Sell(); Thread t1=new Thread(s,"窗口1"); Thread t2=new Thread(s,"窗口2"); Thread t3=new Thread(s,"窗口3"); t1.start(); t2.start(); t3.start(); } }
卖票案例的思考
刚才讲解了电影院卖票程序,好像没有什么问题。但是在实际生活中,售票时出票也是需要时间的所以,在出售一张票的时候,需要一点时间的延迟,接下来我们去修改卖票程序中卖票的动作:每次出票时间100毫秒,用sleep0方法实现
package zyy04; public class Sell implements Runnable{ private int tickets=10; @Override public void run() { while (true) { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票"); tickets--; } } } }
卖票出现了问题
相同的票出现了多次出现了负数的票问题原因:
线程执行的随机性导致的
卖票案例数据安全问题的解决
为什么出现问题?(这也是我们判断多线程程序是否会有数据安全问题的标准)
是否是多线程环境是否有共享数据
是否有多条语句操作共享数据如何解决多线程安全问题呢?
基本思想:让程序没有安全问题的环境怎么实现呢?
把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可Java提供了同步代码块的方式来解决
同步代码块
锁多条语句操作共享数据,可以使用同步代码块实现
格式:
synchronized(任意对象){
多条语句操作共享数据的代码}synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁
同步的好处和弊端:
好处:解决了多线程的数据安全问题
弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率package zyy04; public class Sell implements Runnable{ private int tickets=10; private Object obj=new Object(); @Override public void run() { while (true) { synchronized (obj) { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票"); tickets--; } } } } }
同步方法
同步方法:就是把synchronized关键字加到方法上
格式:
修饰符synchronized返回值类型方法名(方法参数){}同步方法的锁对象是什么呢?
This同步静态方法:就是把synchronized关键字加到静态方法上
格式:
修饰符staticsynchronized返回值类型方法名(方法参数){}同步静态方法的锁对象是什么呢?
类名.class