完成火车站售票程序的模拟。
要求:
(1)总票数1000张;
(2)10个窗口同时开始卖票;
(3)卖票过程延时1秒钟;
(4)不能出现一票多卖或卖出负数号票的情况。
代码:
1 package com.company; 2 3 class MyThread implements Runnable 4 { 5 private int ticket = 1000; 6 7 public void run() 8 { 9 for (int i = 0; i < 1000; i++) 10 { 11 synchronized (this) //此处this指的是进入此代码块的线程对象。一个时间内只能有一个线程得到执行,另一个线程必须等待当前线程执行完这个代码块以后才能执行下一个代码块。 12 { 13 if (ticket > 0) 14 { 15 System.out.println(Thread.currentThread().getName() + "售票,剩余票数:" + ticket--); 16 } 17 else if (ticket == 0) 18 { 19 System.out.println(Thread.currentThread().getName() + "售票,票已售完!"); 20 break; 21 } 22 try 23 { 24 Thread.sleep(1000); 25 } 26 catch (InterruptedException e) 27 { 28 e.printStackTrace(); 29 } 30 } 31 } 32 } 33 } 34 public class Main 35 { 36 public static void main(String[] args) 37 { 38 MyThread my=new MyThread(); 39 new Thread(my,"窗口一").start(); 40 new Thread(my,"窗口二").start(); 41 new Thread(my,"窗口三").start(); 42 new Thread(my,"窗口四").start(); 43 new Thread(my,"窗口五").start(); 44 new Thread(my,"窗口六").start(); 45 new Thread(my,"窗口七").start(); 46 new Thread(my,"窗口八").start(); 47 new Thread(my,"窗口九").start(); 48 new Thread(my,"窗口十").start(); 49 } 50 }
遇到的问题:
一开始的代码,无法做到是个窗口同时售票,总会有窗口没有运行,代码如下:
package com.company; class MyThread implements Runnable { private int ticket = 1000; public void run() { for (int i = 0; i < 1000; i++) { synchronized (this) { if (ticket > 0) { System.out.println(Thread.currentThread().getName() + "售票,剩余票数:" + ticket--); } else if (ticket == 0) { System.out.println(Thread.currentThread().getName() + "售票,票已售完!"); break; } } } } } public class Main { public static void main(String[] args) { MyThread my=new MyThread(); new Thread(my,"窗口一").start(); new Thread(my,"窗口二").start(); new Thread(my,"窗口三").start(); new Thread(my,"窗口四").start(); new Thread(my,"窗口五").start(); new Thread(my,"窗口六").start(); new Thread(my,"窗口七").start(); new Thread(my,"窗口八").start(); new Thread(my,"窗口九").start(); new Thread(my,"窗口十").start(); } }
(错误)运行结果:
解决办法:
加上
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
对异常进行处理的方法就是用try-catch
运行结果:
本次作业总结:
synchronized(this):
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用
本周预习内容:
泛型:
定义:泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
使用:泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法
泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。
最典型的就是各种容器类,如:List、Set、Map。