JAVA并发多线程:卖票例子最简单版(第一集)——代码篇

卖票代码(最初的样子)

class TicketForNoSychronized{
	//买了多少张?
	private static Integer saledNum = 0;
	//还剩多少张?50张!!!
	private static Integer lastedNum = 50;
	//注意此处方法为最最最最普通的方法---卖票
	public void sale() {
		//卖之前判断一下剩的票是否大于0
		if(lastedNum>0) {
			//睡眠300毫秒=业务员在操作收钱打票
			try {
				//超级好用的TimeUnit
				TimeUnit.MICROSECONDS.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//醒来(一切还是当初的样子吗)=业务员买完了,调整下库存
			//剩余的票减少一张
			lastedNum--;
			//卖出的票加一张
			saledNum++;
			//给我们看看结果
			System.out.println(
				Thread.currentThread().getName()
				+"线程卖出了"+saledNum
				+"还剩"+lastedNum+"张票");
		}
	}
}

执行卖票的代码(多线程,来两个窗口卖票)

public class testNoSychronized {
	
	public static void main(String[] args) {
		//首先你得有个卖票站点,我们亲切地称它为对象,(此时为实例对象)
		TicketForNoSychronized object = 
			new TicketForNoSychronized();
		//创建个A线程,重写个run方法,并开启执行(此处为潮流的lambda表达式)
		new Thread(()->{
			//怎么执行?---->执行55次卖票,当然,卖没了就不卖是在卖票代码里给我保证的
			for (int i = 0;i<55;i++) {
				object.sale();
			}
		},"A").start();
		//同样,窗口2 ,同时干!
		new Thread(()->{
			for (int i = 0;i<55;i++) {
				object.sale();
			}
		},"B").start();
	}

}

结果:

在这里插入图片描述
不但卖超了,而且怎么没有还剩3张票的记录?怎么还剩2张报告了2次?

我是卖票站点的老板,我反思:

  1. 执行没问题,一个站点,两个窗口同时卖。(执行方法不变)
  2. 把这个票加锁,让这两个窗口依次有序执行卖票。(站点整顿改变)

华丽的分割线 华丽的分割线 华丽的分割线 华丽的分割线 华丽的分割线 华丽的分割线

卖票代码(加锁变身术一)

class TicketForNoSychronized{
	//不变
	private static Integer saledNum = 0;
	//不变
	private static Integer lastedNum = 50;
	//变//////此处加个synchronized//////////////////////////////////////
	public synchronized void sale() {
		//不变
		if(lastedNum>0) {
			//不变
			try {
				//不变
				TimeUnit.MICROSECONDS.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//不变
			lastedNum--;
			//不变
			saledNum++;
			//不变
			System.out.println(
				Thread.currentThread().getName()
				+"线程卖出了"+saledNum
				+"还剩"+lastedNum+"张票");
		}
	}
}

结果:

在这里插入图片描述
多次试验结果都很合心意,如我所愿

并发编程如果到这里就结束了该多好呢。。。

我是卖票站点的老板,我反思:

有些人因为贪婪,想得更多的东西,却把现在所有的也失掉了。 ——伊索

  1. 站点稳定了,再开家连锁店吧 (执行方法里创建两个对象)
  2. 在连锁店开两个窗口(执行方法里增加创建两个线程)
  3. 票永远是这50张(扩大供货指日可待)(卖票的那一套不变)

华丽的分割线 华丽的分割线 华丽的分割线 华丽的分割线 华丽的分割线 华丽的分割线

执行卖票的代码(俩对象变身术A)

public class testNoSychronized {
	
	public static void main(String[] args) {
		//首先你得有个卖票站点,我们亲切地称它为对象,(此时为实例对象)
		TicketForNoSychronized object = 
			new TicketForNoSychronized();
		////////变////////////////////////
		TicketForNoSychronized object2 = 
			new TicketForNoSychronized();
		//不变
		new Thread(()->{
			//怎么执行?---->执行55次卖票,当然,卖没了就不卖是在卖票代码里给我保证的
			for (int i = 0;i<55;i++) {
				object.sale();
			}
		},"A").start();
		//不变
		new Thread(()->{
			for (int i = 0;i<55;i++) {
				object.sale();
			}
		},"B").start();
		//新增1号
		new Thread(()->{
			for (int i = 0;i<55;i++) {
				object2.sale();
			}
		},"1号").start();
		//新增2号
		new Thread(()->{
			for (int i = 0;i<55;i++) {
				object2.sale();
			}
		},"2号").start();
	}

}

结果:

在这里插入图片描述
很显然一切都回到最初那个样子混乱了

我是卖票站点的老板,我反思:

  1. 执行没问题,2个站点,四个窗口同时卖那50张。(执行方法不变)
  2. 把这个票加锁,让这两个窗口依次有序执行卖票。(站点整顿改变)

华丽的分割线 华丽的分割线 华丽的分割线 华丽的分割线 华丽的分割线 华丽的分割线

卖票代码(加锁+加静 变身术二)

class TicketForNoSychronized{
	//不变
	private static Integer saledNum = 0;
	//不变
	private static Integer lastedNum = 50;
	//变//////此处加个synchronized再加个static//////////////////////////////////////
	public static synchronized void sale() {
		//不变
		if(lastedNum>0) {
			//不变
			try {
				//不变
				TimeUnit.MICROSECONDS.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//不变
			lastedNum--;
			//不变
			saledNum++;
			//不变
			System.out.println(
				Thread.currentThread().getName()
				+"线程卖出了"+saledNum
				+"还剩"+lastedNum+"张票");
		}
	}
}

番外篇:这个static加在synchronized前和后都可以,具体为什么?不知道

结果:

在这里插入图片描述
很显然一切都好起来了

我是卖票站点的老板,我反思:

  1. 满足了最基本的业务扩张

具体原理,且听下回分说

发布了11 篇原创文章 · 获赞 0 · 访问量 227

猜你喜欢

转载自blog.csdn.net/weixin_43885975/article/details/104798612
今日推荐