欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

面试编程题的实验

程序员文章站 2022-07-10 15:02:16
...
昨天某知名互联网企业对我做了一个电话面试。然后叫我在他给的一个网址上面做一个编程题。
题目是这样的。



共计9个苹果,有2只猴子,一个猴子每次拿2个苹果,一个猴子每次拿3个苹果,如果剩余的苹果不够猴子每次拿的数量,则2只猴子停止拿苹果,请用java多线程模拟上面的描述




描述是挺简单的。但当在电话面试的情况下,又是一个比较知名公司的限时下。我那小心肝是紧张的,再加上是在一个非IDE环境下写代码很多API记不详细,所以导致我写出了下面的这个诡异的版本。真是丢脸呀。



//monkey2 是类似 monkey1的。当时紧张还没写完然后自己的网络突然异常了,然后就断联了。注定是抓不住机会好好表现了
private static volatile int appleStoreCount = 9;

public static void main(String... args) {
  
  ReentrantLock lock = new ReentrantLock();
	Runnable monkey1 = () -> {
      
      int takeOffNum = 2;
      
      outer : while(true){
        lock.lock()
       while( appleStoreCount >= takeOffNum) {
         
         appleStoreCount -= takeOffNum;
         lock.unlock();// 这个业务简单假设不出现异常,所以不放finally里了
         continue outer;
       }
        break;
      };
    };
   Runnable monkey2 = () -> {
     
    int takeOffNum = 3;
      while( appleStoreCount.get() > = takeOffNum){
       
         if (appleStoreCount.compareAndDecrement(takeOffNum) == false){
        	
           continue;
         }
      };
   };
  
  Thread monkey1Task = new Thread(monkey1);
  Thread monkey2Task = new Thread(monkey2);
  monkey1Task.start();
  monkey1Task.start();
     
     
     
   }




但这代码真不是我最初设想的那样的。真不知我这心里素质是什么情况了。
下面给出我冷静后并且未查询资料,只是在IDE环境下写出的代码。




private static final AtomicInteger STORE_COUNT = new AtomicInteger(9);

@Test
	public void tttt() {

		Runnable monkey1 = () -> {

			String monkeyName = "monkey1";
			int takeoffNum = 2,
					storeCountByGet = 0;
			while ((storeCountByGet = STORE_COUNT.get()) >= takeoffNum) {

				if (STORE_COUNT.compareAndSet(storeCountByGet, storeCountByGet - takeoffNum)) {

					System.out.println(monkeyName + "争抢水果成功 => " + takeoffNum);
				} else {

					System.out.println(monkeyName + "争抢水果失败");
				}
			}
		};
		Runnable monkey2 = () -> {

			String monkeyName = "monkey2";
			int takeoffNum = 3,
					storeCountByGet = 0;
			while ((storeCountByGet = STORE_COUNT.get()) >= takeoffNum) {

				if (STORE_COUNT.compareAndSet(storeCountByGet, storeCountByGet - takeoffNum)) {

					System.out.println(monkeyName + "争抢水果成功 => " + takeoffNum);
				} else {

					System.out.println(monkeyName + "争抢水果失败");
				}
			}
		};

		Thread m1Task = new Thread(monkey1);
		Thread m2Task = new Thread(monkey2);
		m2Task.start();
		m1Task.start();
	}


输出如下
monkey2争抢水果失败
monkey1争抢水果成功 => 2
monkey2争抢水果成功 => 3
monkey1争抢水果成功 => 2
monkey1争抢水果成功 => 2


这一个才是我最初设想的实现。只能说较差的心理素质和非IDE环境导致了发挥失常。可惜呀。这个实现不算完美,但算符合需求且干净的实现。


————————————————不希望被忽视的分割线——————————

这部分是我看到题目时所想到的一个扩展问题。



共计9个苹果,有2只猴子,一个猴子每次拿2个苹果,一个猴子每次拿3个苹果,如果剩余的苹果不够猴子每次拿的数量,则2只猴子停止拿苹果,两只猴子依次拿取苹果。请用java多线程模拟上面的描述



下面是我实现
private volatile Integer[] storeCount = { 9 };

	private volatile int flagInt = 2;

	@Test
	public void tttt1() {

		Runnable monkey1 = () -> {

			String monkeyName = "monkey1";
			int takeoffNum = 2,
					flagVal = 1;

			synchronized (storeCount) {

				try {
					while (storeCount[0].intValue() >= takeoffNum) {
						if (flagInt != flagVal) {

							storeCount.wait();
						}
						if (storeCount[0].intValue() >= takeoffNum) {

							storeCount[0] -= takeoffNum;
							System.out.println(monkeyName + "争抢水果成功 => " + takeoffNum);
							flagInt = 2;
							storeCount.notifyAll();
						}
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		};
		Runnable monkey2 = () -> {

			String monkeyName = "monkey2";
			int takeoffNum = 3,
					flagVal = 2;

			synchronized (storeCount) {

				try {
					while (storeCount[0].intValue() >= takeoffNum) {
						if (flagInt != flagVal) {

							storeCount.wait();
						}
						if (storeCount[0].intValue() >= takeoffNum) {

							storeCount[0] -= takeoffNum;
							System.out.println(monkeyName + "争抢水果成功 => " + takeoffNum);
							flagInt = 1;
							storeCount.notifyAll();
						}
					}
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		};

		Thread m1Task = new Thread(monkey1);
		Thread m2Task = new Thread(monkey2);
		m1Task.start();
		m2Task.start();
	}


输出如下
monkey2争抢水果成功 => 3
monkey1争抢水果成功 => 2
monkey2争抢水果成功 => 3


将flagInt的初始值改成1后的输出如下
monkey1争抢水果成功 => 2
monkey2争抢水果成功 => 3
monkey1争抢水果成功 => 2