Java自学 day23_多线程18-22 笔记

18-继承Thread类的方式卖电影票案例

需求:

  某电影院目前正在上映贺岁大片,共有100张票,而它有3个售票窗口售票,请设计一个程序模拟该电影院售票。

两种方式实现
       继承Thread类
       实现Runnable接口

注意:此代码只是为了配合学习此小结,仍不完善

 1 public class day23_18继承Thread类的方式卖电影票案例 {
 2     public static void main(String[] args) {
 3         //创建线程对象
 4         SellTicket1 st1=new SellTicket1();
 5         SellTicket1 st2=new SellTicket1();
 6         SellTicket1 st3=new SellTicket1();
 7         
 8         //给线程对象起名字
 9         st1.setName("窗口1");
10         st2.setName("窗口2");
11         st3.setName("窗口3");
12         
13         //启动线程
14         st1.start();
15         st2.start();
16         st3.start();
17 
18     }
19 
20 }
21 
22 class SellTicket1 extends Thread {
23     // 为了让多个线程对象共享这个100张票,其实应该用静态修饰
24     private static int ticket = 100;
25 
26     @Override
27     public void run() {
28         // int ticket=100;这样写每个线程进来都会走到这里,每个线程对象相当于买的是自己的那100张票,不合理,所以应该定义到外面
29         // while(true)是为了模拟一直有票
30         while (true) {
31             if (ticket > 0) {
32                 System.out.println(getName() + "正在出售第" + (ticket--) + "张票");
33             }
34         }
35 
36     }
37 }
代码练习案例

19-实现Runnable接口的方式卖电影票案例

注意:此代码只是为了配合学习此小结,仍不完善

 1 public class day23_19实现Runnable接口的方式卖电影票案例 {
 2 
 3     public static void main(String[] args) {
 4         SellTicket2 st = new SellTicket2();
 5         Thread t1 = new Thread(st, "窗口1");
 6         Thread t2 = new Thread(st, "窗口2");
 7         Thread t3 = new Thread(st, "窗口3");
 8         t1.start();
 9         t2.start();
10         t3.start();
11 
12     }
13 
14 }
15 
16 class SellTicket2 implements Runnable {
17     // 定义100张票
18     private int tickets = 100;
19 
20     @Override
21     public void run() {
22         while (true) {
23             if (tickets > 0) {
24                 System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");
25             }
26         }
27 
28     }
29 
30 }
代码练习案例

20-卖电影票出现了同票和负数票的原因分析

  • 我们前面讲解过电影院售票程序,从表面上看不出什么问题,但是在真实生活中,售票时网络是不能实施传输的,总是存在延迟的情况,所以,在出售一张票以后,需要一点时间的延迟
  • 改实现接口方式的卖票程序:每次卖票延迟100毫秒
 1 public class day23_20卖电影票出现了同票和负数票的原因分析 {
 2     public static void main(String[] args) {
 3         SellTicket3 st = new SellTicket3();
 4         Thread t1 = new Thread(st, "窗口1");
 5         Thread t2 = new Thread(st, "窗口2");
 6         Thread t3 = new Thread(st, "窗口3");
 7         t1.start();
 8         t2.start();
 9         t3.start();
10 
11     }
12 }
13 class SellTicket3 implements Runnable {
14     // 定义100张票
15     private int tickets = 100;
16 
17     @Override
18     public void run() {
19         while (true) {
20             if (tickets > 0) {
21                 try {
22                     Thread.sleep(100);
23                 } catch (InterruptedException e) {
24                     e.printStackTrace();
25                 }
26                 System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");
27             }
28         }
29 
30     }
31 
32 }
代码练习案例

实现Runnable接口的方式实现
通过加入延迟后,就产生了2个问题:
A:相同的票卖了多次
  CPU的一次操作必须是原子性的
B:出现了负数票
  随机性和延迟导致的

21-线程安全问题的产生原因分析

●首先想为什么出现问题?(也是我们判断是否有问题的标准)
●是否是多线程环境
●是否有共享数据
●是否有多条语句搡作共享数据
 
如何解决多线程安全问题呢?
把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可。
 

22-同步代码块的方式解决线程安全问题

思想:
把多条语句操作共享数据的代码给包成一个整体,让某个线程在执行的时候,别人不能来执行。
问题是我们不知道怎么包啊?其实我也不知道,但是Java给我们提供了:同步机制。
同步代码块:
  synchronized (对象) {
      需要同步的代码;
  }

注意:
同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。
多个线程必须是同一把锁。

 1 public class day23_22同步代码块的方式解决线程安全问题 {
 2     public static void main(String[] args) {
 3         SellTicket4 st = new SellTicket4();
 4         Thread t1 = new Thread(st, "窗口1");
 5         Thread t2 = new Thread(st, "窗口2");
 6         Thread t3 = new Thread(st, "窗口3");
 7         t1.start();
 8         t2.start();
 9         t3.start();
10 
11     }
12 }
13 class SellTicket4 implements Runnable {
14     // 定义100张票
15     private int tickets = 100;
16     //创建锁对象 注意一定要让锁变成一个共享的东西
17     private Object obj=new Object();
18 
19     @Override
20     public void run() {
21         while (true) {
22             synchronized (obj) {
23                 if (tickets > 0) {
24                     try {
25                         Thread.sleep(100);
26                     } catch (InterruptedException e) {
27                         e.printStackTrace();
28                     }
29                     System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票");
30                 }
31                 
32             }
33         }
34 
35     }
36 
37 }
代码练习案例

猜你喜欢

转载自www.cnblogs.com/htbht2000/p/12550330.html