/*
* 需求, 写一个程序来解决生产消费者问题(多线程);
*
* 首先定义一个类Resoucer来描述商品;
* 这个Resoucer类应该有一个int类型的成员变量用来修饰当前商品的编号;
* 还应该有一个String类型的变量name用来记录当前商品名称;
* 此外还应该有一个boolean类型的变量用来标记当前是否有商品被生产或者消费;
* 然后定义一个类Producer来实现Runnable的run方法;
* 再定义一个类Consumer来实现Runnable中的run方法;
*
*
* 总算搞懂了这里为什么编译运行, 运行到一半会卡住不动了:
*
* 我们这里总共有五条线程
* main线程......也就是主函数线程;
* Thread0 和 Thread1 这两条线程是生产者线程
* Thread2 和 Thread3 这两条线程是消费者线程
*
* 首先Thread0生产一个商品, 然后flag被赋值为true, 并进入了线程池中,
* 此时Thread1线程开启, 因为flag为true,Thread1也进入了线程池,
*
* Thread2线程开启, 消费了Thread0生产的商品后, 将flag赋值为false, 并进入线程池,
* Thread3经过判断之后同样进入线程池...
*
* 到目前为止线程池中的线程队列为:
*
* Thread0, Thread1, Thread2, Thread3;
*
* 当然最先唤醒的是Thread0,此时flag的值为false, Thread0便跳出while循环;
* 生产完商品之后, 将flag赋值为true, 并将线程池中的第一个线程唤醒(也就是Thread1, Thread1仅仅是获取资格, 并没有执行权)
* 然后Thread0在执行flag==true判断的时候, 又被扔进了线程池, 此时把控制权交给了Thread1, 很不幸, 此时Thread1这条线程,
* 执行阶段正好在while(flag == true)这个循环中, 更不幸的是, flag正好为true; 此时就是一个死循环了, 而且Thread1这条线程
* 也没法notify Thread2或者Thread3来消费商品, 于是, 大家都睡了.....
*
*
*
* 总结: 当然, 不同的机器不同的状态下, 所执行的线程顺序可能不一样,
* 但是都有可能遇到这种全部等待的情况,
* 造成这种情况的原因就是某一线程又唤醒了本类线程,
* 而且本类线程不满足条件,导致刚唤醒的线程又直接wait()了,
* 没法唤醒对方线程,所以程序就卡住不动了, 这应该不叫死锁, 而是全部等待....
*/
class Resoucer
{
private String name;
private int cnt = 1;
private boolean flag = false;
public synchronized void set(String name)
{
while(flag == true)
try{this.wait();}catch(Exception e){}
this.name = name + ".....id =" + cnt++;
System.out.println(Thread.currentThread().getName() + this.name + "...生产者...");
try{Thread.sleep(5);}catch(Exception e){}
flag = true;
this.notify();
}
public synchronized void out()
{
while(flag == false)
try{this.wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName() + this.name + "_______消费者______");
try{Thread.sleep(5);}catch(Exception e){}
flag = false;
this.notify();
}
}
class Producer implements Runnable
{
Resoucer rc;
Producer(Resoucer rc)
{
this.rc = rc;
}
public void run()
{
while(true)
{
rc.set("+++商品+++");
}
}
}
class Consumer implements Runnable
{
Resoucer rc;
Consumer(Resoucer rc)
{
this.rc = rc;
}
public void run()
{
while(true)
{
rc.out();
}
}
}
class demo
{
public static void main(String[] args)
{
Resoucer rc = new Resoucer();
new Thread(new Producer(rc)).start();
new Thread(new Producer(rc)).start();
new Thread(new Consumer(rc)).start();
new Thread(new Consumer(rc)).start();
}
} |
|