码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-06-18 20:09:32      阅读:156      评论:0      收藏:0      [点我收藏+]

标签: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 + "瓶可乐");
		
	}
}


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

本文出自 “行意天下” 博客,请务必保留此出处http://4259297.blog.51cto.com/4249297/1663206

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

标签:java数据结构算法

原文地址:http://4259297.blog.51cto.com/4249297/1663206

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!