一、需求描述
某电影院目前正在上映国产大片,共有1000张票,而它有2个窗口卖票,请设计一个程序模拟该电影院卖票
二、实现方式
1、继承Thread类的方式
自定义开发一个MyThread类,来继承Thread类,重写run方法,定义一个ticket共享变量,表示当前卖的是第几张票,一定要使用static关键字来修饰,这样可以确保每一个线程对象都共享这一个变量。具体代码如下:
MyThread类
package com.hidata.hiops.paas.demo; /** * @Description : * @Date: 2023-10-08 10:38 */ public class MyThread extends Thread { public static int ticket = 0; @Override public void run() { while (true){ synchronized (MyThread.class){ if (ticket < 1000){ try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } ticket ++; System.out.println(getName() + "正在卖第" + ticket + "张票, 剩余 " + (1000 - ticket) + "张"); }else{ break; } } } } }
测试类
package com.hidata.hiops.paas.demo; /** * @Description : * @Date: 2023-10-08 10:46 */ public class TestDemo { public static void main(String[] args) { /** *方式一:继承Thread类 */ MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); t1.setName("窗口1"); t2.setName("窗口2"); t1.start(); t2.start(); } }
运行结果
...................... 窗口1正在卖第978张票, 剩余 22张 窗口1正在卖第979张票, 剩余 21张 窗口1正在卖第980张票, 剩余 20张 窗口1正在卖第981张票, 剩余 19张 窗口1正在卖第982张票, 剩余 18张 窗口1正在卖第983张票, 剩余 17张 窗口2正在卖第984张票, 剩余 16张 窗口2正在卖第985张票, 剩余 15张 窗口2正在卖第986张票, 剩余 14张 窗口2正在卖第987张票, 剩余 13张 窗口2正在卖第988张票, 剩余 12张 窗口2正在卖第989张票, 剩余 11张 窗口2正在卖第990张票, 剩余 10张 窗口2正在卖第991张票, 剩余 9张 窗口2正在卖第992张票, 剩余 8张 窗口2正在卖第993张票, 剩余 7张 窗口2正在卖第994张票, 剩余 6张 窗口2正在卖第995张票, 剩余 5张 窗口2正在卖第996张票, 剩余 4张 窗口2正在卖第997张票, 剩余 3张 窗口2正在卖第998张票, 剩余 2张 窗口2正在卖第999张票, 剩余 1张 窗口2正在卖第1000张票, 剩余 0张
2、实现Runnable接口的方式
自定义开发一个MyRun类,来实现Runnable接口,重写run方法,定义一个ticket变量,表示当前卖的是第几张票,此时ticket变量,可以不用static关键字来修饰,因为只会创建一个MyRun实例,所以不存在变量不一致的问题,具体代码如下:
MyRun类
package com.hidata.hiops.paas.demo; /** * @Description : * @Date: 2023-10-08 10:50 */ public class MyRun implements Runnable { int ticket = 0; @Override public void run() { while (true){ synchronized (MyRun.class){ if (ticket < 1000){ try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } ticket ++; System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票, 剩余 " + (1000 - ticket) + "张"); }else{ break; } } } } }
测试类
package com.hidata.hiops.paas.demo; /** * @Description : * @Date: 2023-10-08 10:46 */ public class TestDemo { public static void main(String[] args) { /** * 方式二:实现Runnable接口 */ MyRun myRun = new MyRun(); Thread tt1 = new Thread(myRun); Thread tt2 = new Thread(myRun); tt1.setName("窗口1"); tt2.setName("窗口2"); tt1.start(); tt2.start(); } }
运行结果
3、使用Lock锁的方式
自定义开发一个MyLock类,来实现Runnable接口,重写run方法,定义一个ticket变量,表示当前卖的是第几张票,此时ticket变量,可以不用static关键字来修饰,再创建一个Lock锁对象,也不需要使用static修饰,所有的线程对象共用一把锁。因为只会创建一个MyRun实例,所以不存在变量不一致的问题,具体代码如下:
MyLock类
package com.hidata.hiops.paas.demo; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Description : * @Date: 2023-10-08 10:50 */ public class MyLock implements Runnable { int ticket = 0; Lock lock = new ReentrantLock(); @Override public void run() { while (true){ lock.lock(); try { if (ticket == 1000){ break; }else{ Thread.sleep(30); ticket ++; System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票, 剩余 " + (1000 - ticket) + "张"); } } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } }
测试类
package com.hidata.hiops.paas.demo; /** * @Description : * @Date: 2023-10-08 10:46 */ public class TestDemo { public static void main(String[] args) { /** * 方式三:使用Lock锁 */ MyLock myLock = new MyLock(); Thread r1 = new Thread(myLock); Thread r2 = new Thread(myLock); r1.setName("窗口1"); r2.setName("窗口2"); r1.start(); r2.start(); } }
运行结果