日期:2014-05-20  浏览次数:20876 次

阻塞问题
本帖最后由 is_zhoufeng 于 2013-10-29 09:42:40 编辑
问题:
一个池塘,有很多鸟和很多鱼,鸟每分钟产生一个后代,鱼每30秒钟产生2个后代。鸟每10秒钟要吃掉一条鱼。建一个池塘,初始化一些鱼和鸟,看看什么时候鸟把鱼吃光。

参考http://blog.csdn.net/ldh911/article/details/7346262写了一个实现
但是有时候会运行成功,有时候却会阻塞在BirdThread的run方法中的world.wait();处 , 求解释



package rabitmq01.test02;

import java.util.concurrent.CountDownLatch;

public class BirdFish {

public static void main(String[] args) throws InterruptedException {

Pond pond = new Pond() ;
pond.birdCount = 5 ;
pond.fishCount = 20 ;

BirdThread bt = new BirdThread(pond) ;
FishThread ft = new FishThread(pond) ;

bt.start();
ft.start();

Thread.sleep(100);  //等上面两个线程先执行

while(pond.fishCount > 0){
synchronized (pond) {
pond.time += 10 ;
pond.countDown = new CountDownLatch(2);
pond.notifyAll();
}
pond.countDown.await();
}

System.exit(-1);  

}

}

class Pond{

int birdCount ;
int fishCount ;
long time ;
CountDownLatch countDown ;

public void printInfo(){
System.out.printf("time[%d]:bird[%d],fish[%d]\n" , time , birdCount , fishCount);
}
}

class BirdThread extends Thread{

Pond  pond ;

public BirdThread(Pond pond){
this.pond = pond ;
}

@Override
public void run() {

while(pond.fishCount > 0){
synchronized (pond) {
try {
pond.wait();
} catch (InterruptedException e) {
e.printStackTrace();

if(pond.time % 10 ==0){
if(pond.fishCount >= pond.birdCount)
pond.fishCount -= pond.birdCount ;
else{
pond.fishCount = 0 ;
}
if(pond.time % 60 == 0){
pond.birdCount += pond.birdCount ;
}
pond.printInfo();
}
}
pond.countDown.countDown();
}
}

}

class FishThread extends Thread{

Pond  pond ;

public FishThread(Pond pond){
this.pond = pond ;
}

@Override
public void run() {
while(pond.fishCount > 0){
synchronized (pond) {
try {
pond.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(pond.time % 30 == 0){
pond.fishCount += pond.fishCount * 2 ;
pond.printInfo();
}
}
pond.countDown.countDown();
}
}

}


------解决方案--------------------
沙发先
------解决方案--------------------
板凳
------解决方案--------------------
地板 三联
------解决方案--------------------
你这个可能会造成死锁的, 鸟线程先阻塞等待主线程唤醒,然后唤醒主线程;主线程也阻塞等待鸟或者鱼线程唤醒再唤醒它们,这个同步顺序会造成条件性的死锁

建议,你的模型可以建得更加简单,把时间控制的部分抽出来放到主线程里,不要混杂在生产者和消费者里
------解决方案--------------------
countdown了之后,鸟线程和鱼线程在wait之前,主线程就notify过了,你就死锁了。

多线程本身控制起来比较麻烦,你不应该把这么多条件变量引入到同步的过程中,很容易出现死锁的,而且这种和时间有关的设计,本身不应该是这样的,你可以试着把time这个东西抽出来专门做一个更新线程来控制,不要在主线程里做同步了