昨天某知名互联网企业对我做了一个
电话面试。然后叫我在他给的一个网址上面做一个编程题。
题目是这样的。
共计9个苹果,有2只猴子,一个猴子每次拿2个苹果,一个猴子每次拿3个苹果,如果剩余的苹果不够猴子每次拿的数量,则2只猴子停止拿苹果,请用java多线程模拟上面的描述
描述是挺简单的。但当在电话面试的情况下,又是一个比较知名公司的限时下。我那小心肝是紧张的,再加上是在一个非IDE环境下写代码很多API记不详细,所以导致我写出了下面的这个版本。真是丢脸呀。
class="java">
//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