题目是这样的。
共计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