A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

[Java] 纯文本查看 复制代码
package com.heima.moreThread多线程;

import java.util.Random;

public class Test02 {

	/**
	 * /*3. 某包子店铺生意火爆,现开5个窗口模拟售卖100个包子,每次每个窗口随机卖出1-5个包子,
		卖完最后一个包子后提示”包子已售完”(必须全部卖出),程序结束.(要求使用Thread类和Runnable两种方式去实现)
	 	* */
	public static void main(String[] args) {
		MyBaoZi mb = new MyBaoZi();
		Thread t1 = new Thread(mb,"窗口1");
		Thread t2 = new Thread(mb,"窗口2");
		Thread t3 = new Thread(mb,"窗口3");
		Thread t4 = new Thread(mb,"窗口4");
		Thread t5 = new Thread(mb,"窗口5");
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
	}

}

class MyBaoZi implements Runnable {
	//总共的包子数,这是共享数据
	private int baozi = 100;
	//设置标记,为输出一次"包子已经卖完了"做准备
	private boolean flag = true;
	//创建随机数对象
	Random r = new Random();
	@Override
	public void run() {
		//获取随机数,相当于获取随机卖出的包子个数
		int i = r.nextInt(5) + 1;
		while (true) {
			synchronized (MyBaoZi.class) {
				//如果剩余的包子数等于0或者是小于0,就直接跳出
				if(baozi <= 0) {
					break;												//跳出
				}
				try {
					Thread.sleep(20);							//防止卖得太快,让程序睡一会
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//这一步的判断的目的是在于只剩下一个包子的时候,怎么样才能卖出去,
				//当获取到的随机数是在包子的剩余范围的时候,交易才能成功
				if (baozi >= i) {
					//获取到卖出之后的剩余包子数
					baozi = baozi - i;
					//输出卖出去包子的信息
					System.out.println(Thread.currentThread().getName() + "...出售了" + i  + "个包子,还剩下" + baozi + "个包子");
				}
			}
			//必须保证是卖最后一个包子的线程执行这一段代码
			synchronized(MyBaoZi.class) {
				if (flag && baozi <= 0) {
					System.out.println("包子已经卖完了");
					flag = false;
				}
			}
		}
	}
	
}

29 个回复

正序浏览
HackSon 发表于 2016-10-13 15:46
英雄所见略同

我去,英雄这个就说大了,我只是凑巧知道这一点点而已,以后还得跟各位多学习
来自宇宙超级黑马专属苹果客户端来自宇宙超级黑马专属苹果客户端
回复 使用道具 举报
梁古叔广 发表于 2016-10-12 18:56
你这个如果最后随机数不是碰巧等于包子数,绝对直接死循环,该线程一直拥有执行权,一直循环,因为你随机数大于 ...

英雄所见略同{:2_31:}
回复 使用道具 举报
回根的落叶 发表于 2016-10-13 00:35
@HackSon 正解,获取随机数必须放进循环内,至于是放在同步代码块外面还是同步代码块里面都是可以的,个 ...

学技术就应该虚心点,如果别人一个善意的提示他都不能接受的话,那我只能呵呵了
回复 使用道具 举报
HackSon 发表于 2016-10-11 21:08
“开启五个线程卖包子,每个线程每次随机获取1-5个包子”,这句话你理解好了没有?意思是每个线程每次循 ...

@HackSon 正解,获取随机数必须放进循环内,至于是放在同步代码块外面还是同步代码块里面都是可以的,个人看法最好放同步代码块里面。。{:2_32:}
回复 使用道具 举报
厉害厉害!
回复 使用道具 举报
chensc 金牌黑马 2016-10-12 22:11:07
28#
学习学习!
回复 使用道具 举报
广叔的代码可行,然, 代码还是臃肿了点,,,可以改的简单点的,...
回复 使用道具 举报
本帖最后由 梁古叔广 于 2016-10-12 19:00 编辑

你这个如果最后随机数不是碰巧等于包子数,绝对直接死循环,该线程一直拥有执行权,一直循环,因为你随机数大于最后的包子数的时候,while循环你没有设置出口,死循环
回复 使用道具 举报
李春林 发表于 2016-10-11 17:45
多线程是什么,你都还没有完全搞懂,每条线程,一次只能获取一个随机数,当随机数在包子剩余范围内时,这 ...

“开启五个线程卖包子,每个线程每次随机获取1-5个包子”,这句话你理解好了没有?意思是每个线程每次循环都随机获取一个随机数作为包子卖出的个数,你这个程序一进去的时候获取一个随机数,之后一直循环,随机数没有重新获取,一直不变,如果你的随机数比包子剩余的数量都大的时候,无法卖出包子,也无法跳出循环,懂吗?麻烦你回去调试好了再说话好吗,遇到别人指出你程序的问题你第一反应不是好好检查程序,而是语言攻击,这样就能表现出你很牛吗?论坛是大家交流学习的地方,不是你装逼的地方,OK?
回复 使用道具 举报
这是我的卖包子,献丑了,希望各位指正;
在循环中加循环是为了保证在最后所剩包子数小于顾客所需数时,让该顾客在该窗口重新买少于或等于所剩包子数量的包子,也就是说该顾客在该窗口说买5个,剩余包子没那么多,我得告诉他没那么多,让他少买点,而不是说剩余不足5个我就不在该窗口卖给给顾客了;
增加第二个随机数是保证顾客说的第二个数一定可以买到也就是顾客第一次说要买5个,销售员说没有5个只有3个,顾客必须买少于3个,因为顾客再说买4个或者5个的话会被认为是找茬的,可能要引起口角,不好.
package com.java;


public class 测试 {



        public static void main(String[] args) {
                //创建5条线程代表5个窗口
                Thread t1 = new BaoZi();
                Thread t2 = new BaoZi();
                Thread t3 = new BaoZi();
                Thread t4 = new BaoZi();
                Thread t5 = new BaoZi();
                //命名
                t1.setName("1号窗口");
                t2.setName("2号窗口");
                t3.setName("3号窗口");
                t4.setName("4号窗口");
                t5.setName("5号窗口");
                //开启线程,开卖
                t1.start();
                t2.start();
                t3.start();
                t4.start();
                t5.start();

        }

}

class BaoZi extends Thread {
        //100个包子
        private static int baoZi = 100;

        @Override
        public void run() {
                //此处循环是为了卖完包子
                while (true) {
                        synchronized (BaoZi.class) {
                                //卖完为止
                                if (baoZi<= 0) {

                                        break;
                                }
                                //此处循环是为了保证最后包子数少于顾客要购买的量(随机数),该顾客在该窗口重新随机数再买
                                while (true) {
                                        //当前窗口当前顾客要购买的包子数
                                        int i = (int) (Math.random() * 5) + 1;
                                        //所剩包子小于顾客想要购买的数量时(告诉该顾客包子数不够,你要买等于或者少于剩余数的包子)
                                        if (i > baoZi) {
                                                //让该顾客在该窗口重新买,而且保证重新买的数量在包子剩余数范围内(第二次随机必须买到)
                                                int t = (int) (Math.random() * baoZi) + 1;
                                                //卖出包子
                                                baoZi -= t;
                                                //判断卖出包子是否有剩余,无剩余则提示卖完并结束本次销售
                                                if (baoZi == 0) {
                                                        System.out.println(this.getName() + "本次卖出" + t
                                                                        + "个包子,一共卖了" + (100 - baoZi) + "个包子,卖完了");
                                                        break;
                                                        //如果卖了之后还有剩余则打印本次销售的信息以及剩余的包子数,并结束本次销售
                                                } else {
                                                        System.out.println(this.getName() + "本次卖出" + t
                                                                        + "个包子,一共卖了" + (100 - baoZi) + "个包子,还剩"
                                                                        + baoZi + "个包子");
                                                        break;
                                                }
                                                //当包子剩余数大于顾客所需购买量时,直接销售不需要顾客再重新随机数
                                        } else {
                                                //卖出包子,并判断是否卖完,打印当次的销售情况和剩余包子数
                                                baoZi -= i;
                                               
                                                if (baoZi == 0) {
                                                        System.out.println(this.getName() + "本次卖出" + i
                                                                        + "个包子,一共卖了" + (100 - baoZi) + "个包子,卖完了");
                                                        break;
                                                } else {
                                                        System.out.println(this.getName() + "本次卖出" + i
                                                                        + "个包子,一共卖了" + (100 - baoZi) + "个包子,还剩"
                                                                        + baoZi + "个包子");
                                                        break;
                                                }
                                        }
                                }
                        }
                }

        }
}
回复 使用道具 举报
回复 使用道具 举报
HackSon 发表于 2016-10-11 10:13
你这样会出现卖不出包子的情况,比如:最后剩下一个包子,可是每个线程的随机数都大于1,因为你获取随机 ...

多线程是什么,你都还没有完全搞懂,每条线程,一次只能获取一个随机数,当随机数在包子剩余范围内时,这条线程才能继续执行下去,不然,线程直接结束,换下一条线程。如果按照你说的,把获取随机数也放在循环里面,那只能是一条线程一直在跑
来自宇宙超级黑马专属苹果客户端来自宇宙超级黑马专属苹果客户端
回复 使用道具 举报
HackSon 发表于 2016-10-11 10:13
你这样会出现卖不出包子的情况,比如:最后剩下一个包子,可是每个线程的随机数都大于1,因为你获取随机 ...

你确定你运行了我的程序了吗??
来自宇宙超级黑马专属苹果客户端来自宇宙超级黑马专属苹果客户端
回复 使用道具 举报
好难的样子,谢谢楼主分享
回复 使用道具 举报
wjhsyy 中级黑马 2016-10-11 10:47:51
19#
多线程一直比较迷糊,看完感觉思路清晰多了
回复 使用道具 举报
李春林 发表于 2016-10-10 19:44
对啊,5条线程,每条线程一次只获取一个随机数,如果不符合要求,那就直接跳出咯,只有获取到的随机数在 ...

你这样会出现卖不出包子的情况,比如:最后剩下一个包子,可是每个线程的随机数都大于1,因为你获取随机数是在循环外面,所以一次循环不符合后再次循环随机数还是不变的,这样包子数一直为1,无法跳出循环,也无法卖出。
回复 使用道具 举报
yu244934256 发表于 2016-10-11 00:38
你怎么搞了2个同步代码块

请看注解
来自宇宙超级黑马专属苹果客户端来自宇宙超级黑马专属苹果客户端
回复 使用道具 举报
你怎么搞了2个同步代码块
回复 使用道具 举报
出问题一般在边界上
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马