java数据结题之-喝可乐的问题

问题如下:

黑马程序员训练营入学考试题

10、 28人买可乐喝,3个可乐瓶盖可以换一瓶可乐,那么要买多少瓶可乐,够28人喝?假如是50人,又需要买多少瓶可乐?(需写出分析思路)

我的思路1:

利用逆向思维和全局思维,假如28个都喝到了可乐,那么会有28个盖子,就可以兑换28/3 = 9(截断,只能买少不能买多)瓶可乐,那么一共就得买28-9 = 19瓶可乐才够28个人喝。

同理:50个人喝可乐,需要50-50/3 =50-16= 34瓶可乐

当然,这个数学计算写代码的话太easy了,我就不演示了。

我的思路2:

利用多线程的等待唤醒机制,代码如下:

/*
 黑马程序员训练营入学考试题
 10、 28人买可乐喝,3个可乐瓶盖可以换一瓶可乐,那么要买多少瓶可乐,够28人喝?假如是50人,又需要买多少瓶可乐?(需写出分析思路)
 利用逆向思维来想的话:
 28个人如果都喝到了可乐,那么会有28个瓶盖,就可以换取28/3 = 9瓶可乐。那么一共需要买28-28/3 = 19瓶可乐才够喝。
 同理,50个人需要买50-50/3 = 34瓶可乐。

 解题思路:
 看这个题的模型有点像生产者与消费者的例子

 定义两个线程
 一个线程买可乐:
 一个线程收集瓶子兑换可乐
 */

//为了突出重点,下面的成员变量就不用private私有化了。
import java.util.concurrent.locks.*;
class Kele
{
	int need = 0;	//需要喝可乐的人数
	int buyCount = 0;	//已经买到的可乐个数
	int returnCount = 0;	//通过盖子兑换回来的可乐个数
	int drokedCount = 0;   //喝掉的可乐个数,也就是盖子的个数。
     
	boolean flag = false;  //记录是否每个人都喝到可乐了。

    boolean flagBuyed = false;   //切换买可乐和换盖子的线程
	//定义一个锁
    private Lock lock = new ReentrantLock();
	private Condition con_buy = lock.newCondition();
	private Condition con_col = lock.newCondition();

	public Kele(int need)
	{
		this.need = need;
	}

	public void buy()	//买可乐
	{
		lock.lock();
		try
		{
			if(flagBuyed)   //如果买了一瓶可乐的话,就得重新计算剩余的瓶盖是否能够3兑换一瓶可乐。
			{
				try
				{
					con_buy.await();
				}
				catch (Exception e)
				{
					throw new RuntimeException("等待异常");
				}
			}
			buyCount++;   //买1瓶可乐给1人喝
			drokedCount++;   //同时买1瓶可乐会多出1盖子

			flagBuyed = true;

			con_col.signal();

		}
		catch(Exception e)
		{
			throw new RuntimeException(e.toString());
		}
		finally
		{
			lock.unlock();
		}
	}

	public void col()	//兑换盖子
	{
		lock.lock();
		try
		{
			if(!flagBuyed)
			{
				try
				{
					con_col.await();
				}
				catch (Exception e)
				{
					throw new RuntimeException("等待异常");
				}

			}

			//方式1-按照常规地来推理(不知道为什么这种方式对于28结果是20,多了一个;而对于50,结果是34,刚好。
			//if(drokedCount == 3)   //如果收集的盖子数量达到3个,就换1瓶可乐,同时盖子就剩下一个了。
			//{
				//returnCount++;
				//drokedCount = 1;    //虽然每次要清零,但同时会多出一个盖子。
			//}

			//方式2-将条件转换一下:3个盖子换一瓶可乐,相当于2个盖子换一瓶无盖的可乐
			if(drokedCount == 2)   //如果收集的盖子数量达到3个,就换1瓶可乐,同时盖子就剩下一个了。
			{
				returnCount++;
				drokedCount = 0;    //只是会多出一瓶可乐,但是盖子没有计数。
			}

			flagBuyed = false;

			con_buy.signal();

		}
		catch(Exception e)
		{
			throw new RuntimeException(e.toString());
		}
		finally
		{
			lock.unlock();
		}
	}

}

class Buyer implements Runnable		//买可乐的线程
{
	Kele k;

	public Buyer(Kele k)
	{
		this.k = k;
	}

	public void run()   //买可乐
	{
		while(k.buyCount + k.returnCount < k.need)
		{
			k.buy();
		}
		k.flag = true;
	}
}

class Collector implements Runnable		//收集盖子的线程,返回可乐。
{
	Kele k;

	public Collector(Kele k)
	{
		this.k = k;
	}

	public void run()
	{
		while(k.buyCount + k.returnCount < k.need)
		{
			k.col();
		}
		k.flag = true;
	}
}

class  RXtest10
{
	public static void main(String[] args) throws Exception
	{
		Kele res = new Kele(50);

		new Thread(new Buyer(res)).start();
		new Thread(new Collector(res)).start();
                
		while(!res.flag){}		//两个子线程没有结束,坚决不让主线程输出。相当于让主线程阻塞了。相当让两个子线程join了,同时它们又可以交替执行。防止子线程还没有标记标签主线程就开始输出了。
		System.out.println(res.need + "个人需要买" + res.buyCount + "瓶可乐");

	}
}

关于这道题,百度一下,有很多的解法可供参考,其一    喝可乐的问题

时间: 2024-11-08 12:42:43

java数据结题之-喝可乐的问题的相关文章

关于填报《国家自然科学基金资助项目结题报告》的补充说明

项目负责人在线提交<结题报告>后,只需打印系统生成的PDF版本,签字后交依托单位. 原<结题报告>撰写提纲与说明中第三项,要求随纸质结题报告提供的附件材料,在电子化后上传即可,无需再随结题报告报送纸质附件材料. <结题报告>中的摘要包括项目摘要和结题摘要两部分,其中项目摘要的内容从计划书中自动生成,结题摘要须以深入浅出的语言简明扼要地概括出项目的精华,如背景.方向.主要内容.重要结果.关键数据及其科学意义等.

《基于Cortex-M4的ucOS-III的应用》课程设计 结题报告

<基于Cortex-M4的ucOS-III的应用>课程设计 结题报告 小组成员姓名:20155211 解雪莹 20155217 杨笛 20155227 辜彦霖 指导教师:娄嘉鹏 一.设计方案及可行性分析 题目要求:ucOS-III的移植:设计三个小实验:单一任务.多任务.并发任务. 1.设计方案 首先运行老师给的范例代码熟悉开发软件和开发板的使用:收集资料简单了解UCOSIII的基本概念,然后进行UCOSIII移植(移植到STM32f407开发板):移植成功后开始进行UCOSIII实例编程(实

【Java每日一题】20161103

package Nov2016; import java.util.List; public class Ques1103 { public void method01(String[] array){} public void method01(Integer[] array){} public void method02(List<String> list){} public void method02(List<Integer> list){} } 今日问题: 请问主程序能否

Java数据类型转换

Java数据类型转换 1.题目    以下代码输出的结果是: /** * @Title:NumEqual.java * @Package:com.you.user.util * @Description:数据类型转换 * @author:Youhaidong(游海东) * @date:2014-7-23 下午9:38:56 * @version V1.0 */ package com.you.user.util; /** * 类功能说明 * 类修改者 修改日期 * 修改说明 * <p>Titl

Java 数据类型转换

int iValue = new Integer(strValue).intValue();String str = intObj.toString();int number = Integer.parseInt(str); public static Object read(String value, Class type) {        Object ret = value;        if (Integer.TYPE.equals(type)) {            ret =

【Java每日一题】20170321

20170320问题解析请点击今日问题下方的"[Java每日一题]20170321"查看(问题解析在公众号首发,公众号ID:weknow619) package Mar2017; public class Ques0321 { public static void main(String[] args) { Ques0321 test = new Ques0321(); test.method(null); } public void method(Object o) { System

【Java每日一题】20170109

20170106问题解析请点击今日问题下方的"[Java每日一题]20170109"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; import java.util.ArrayList; import java.util.List; public class Ques0109<T> { private T t = new T(); private T[] array = new T[3]; private List<T&

【Java每日一题】20161212

package Dec2016;      public class Ques1212 {      public static void main(String[] args){          System.out.println(10.00-9.60);      }   } 今日问题: 请问主程序中输出结果是什么?(点击以下"[Java每日一题]20161212"查看20161209问题解析) 题目原发布于公众号.简书:[Java每日一题]20161212,[Java每日一题

【Java每日一题】20161201

20161130问题解析请点击今日问题下方的"[Java每日一题]20161201"查看 package Dec2016; public class Ques1201 { public static void main(String[] args) { new Ques1201().sum(1, 2); } public void sum(int num1, int num2){ int temp = num1 + num2; System.out.println("没使用变