电影院售票系统的模拟及利用synchronized方法实现同步

本文详细介绍了Java中实现线程的两种方式:继承Thread类和实现Runnable接口,并比较了两者的优缺点。接着,通过电影院售票系统模拟案例,探讨了线程的生命周期,包括新建、就绪、执行和死亡状态。在售票过程中,发现了线程安全问题,即可能出现的同票和负票现象。最后,引入了同步方法的概念,以解决线程安全问题。
摘要由CSDN通过智能技术生成

前面我们学习了进程的两种实现方式,第一种:继承Thread类,第二种:实现Runnable接口,首先我们来对比一下两种实现方式:

第一种方式:

    1)自定义MyThread 类继承自Thread

    2)重写Thread类中的run()方法

    3)创建MyThread类对象,分别去启动线程

注意:启动线程的时候不调用run()方法,因为run()不能作为启动线程的方法,该方法的调用相当于调用一个普通方法,并不会出现线程执行的一种随机性!所以启动线程用的是start()方法,start方法的执行是通过JVM调用run方法,但一个进程不要连续启动,否则会出现非法线程状态异常!

第二种方式:

    1)自定义MyRunnable类实现Runnable接口

    2)实现接口的run()方法

    3)创建MyRunnable类对象,创建Thread类对象,将MyRunnable类对象作为参数进行传递,分别启动线程。

那么你可能会问:既然已经有了第一种实现方式,为什么还会有第二种呢?因为第二种方式实际上是优于第一种的

1)避免了Java单继承的一种局限性

2)更符合Java面向对象的一种设计原则:面向接口编程。将代码的实现和资源对象(MyRunnable)有效地分离开来(数据分离原则)


接下来说一下线程的生命周期:线程从开始创建的时候,一直到线程的执行,最后到线程的终止!

    新建线程:此时线程没有执行执行资格,没有执行权。

    线程就绪:线程有执行资格了,但是没有执行权,一旦该线程抢到了CPU的执行权,线程就开始执行了。

    在执行线程之前,线程还可能会阻塞,如sleep()和wait()方法,此时线程处于阻塞状态,睡眠时间到了或执行notify()方法来唤醒进程,线程对象.start();

    线程执行:线程有执行资格,并且有执行权,此时该线程如果被别的线程抢占到了CPU的执行权,线程就处于就绪的状态。

    线程死亡:线程执行完毕,会被垃圾回收线程中的垃圾回收器及时从内存中释放掉!


这次我们就通过这两种方式来实现一个电影院售票的小案例:

需求:某电影院出售某些电影的票(复联3,红高粱....),有三个窗口同时进行售票(100张票),请您设计一个程序,模拟电影院售票
  两种方式:
  继承

  接口

方式一:

//SellTicket线程
public class SellTicket extends Thread {
	
	//为了不让外界更改这个类中的数据,用private修饰
	//要让每一个线程都使用同一个数据,应该用static修饰
	private static int tickets = 100 ;

	@Override
	public void run() {
		//为了模拟电影卖票(模拟一直有票)
		//死循环
		//st1,st2,st3都有执行这个里面的方法
		while(true) {
			if(tickets>0) {
				System.out.println(getName()+"正在出售第"+(tickets--)+"张票");
			}
		}
	}
}
public class SellTicketDemo {
	
	public static void main(String[] args) {
		
		//创建三个子线程,分别代码三个窗口
		SellTicket st1 = new SellTicket() ;
		SellTicket st2 = new SellTicket(
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值