黑马程序员技术交流社区
标题:
多线程生产者消费者问题
[打印本页]
作者:
王冰
时间:
2012-7-5 04:46
标题:
多线程生产者消费者问题
本帖最后由 王冰 于 2012-7-5 16:58 编辑
毕老师在视频中是用while来判断标记的,这样不能控制次数,只能强制程序结束,我想问下有谁能用for循环这种方式重写,这样就既可以判断标记,还可以控制程序运行的次数。
作者:
孙飞
时间:
2012-7-5 08:06
本帖最后由 feigecal 于 2012-7-5 20:06 编辑
因为每个线程的执行次数是不确定 的,面for循环一般是在明确循环次数的时候用比较合适,所以这里用while比较好了些,再说了这里的while的作用只是让线程每次都去判断一下标记,以防出现两个线程同时挂在判断标记之后,然后再执行时没有判断标记而出现安全问题。
class Resource
{
private String name;
private int count=1;
private boolean flag=false;
public synchronized void setName(String name)
{
while(flag)
try{this.wait();}catch(Exception e){}//如果这里是if的话,那么线程t1进来后判断然后执行,最后返回来再判断时flag为true,会等在这里,这里t2也进来后,也会挂在这里,然后消费者线程运行,然后再次唤醒线程t1和t2的时候,t2就不用再判断标记,所以会出安全问题所以要用while,可以使t2在执行之前再对标记进行判断
this.name=name+"----"+count++;
System.out.println(Thread.currentThread().getName()+"---shengchan---"+this.name);
flag=true;
this.notifyAll();//这里不仅唤醒了对方,也唤醒 了自己方的,自己方的也会抢夺执行权
}
public synchronized void out()
{
while(!flag)
try{this.wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"---xiaofei---"+this.name);
flag=false;
this.notifyAll();
}
}
class Producer implements Runnable
{
private Resource rec;
Producer(Resource rec)
{
this.rec=rec;
}
public void run()
{
while(true)
{
rec.setName("shangpin");
}
}
}
class Consume implements Runnable
{
private Resource rec;
Consume(Resource rec)
{
this.rec=rec;
}
public void run()
{
while(true)
{
rec.out();
}
}
}
class ShopDemo
{
public static void main(String[] args)
{
Resource r=new Resource();
Producer p=new Producer(r);
Consume c=new Consume(r);
Thread t1=new Thread(p);
Thread t2=new Thread(p);
Thread t3=new Thread(c);
Thread t4=new Thread(c);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
复制代码
可以把它改成下面的更方便,其中 Condition将Object
监视器方法wait notify
和notifyAll分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为每个对象提供多个等待,其中,Lock 替代了synchronized方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
import java.util.concurrent.locks.*;
class Resource
{
private String name;
private int count = 1;
private boolean flag = false;
private Lock lock=new ReentrantLock();//创建一个显式的锁,替代了synchronized
Condition condition_pro=lock.newCondition();//Condition 替代了 Object 监视器方法的使用,因为Condition是一个接口,所以要用Lock的newCondition方法来返回一个特定锁的实例,来完成对不同对象提供等待和唤醒
Condition condition_con=lock.newCondition();
public void set(String name)throws InterruptedException
{
lock.lock();
try
{
while(flag)
condition_pro.await();
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
condition_con.signal();//只唤醒消费者线程
}
finally
{
lock.unlock();//无论判断标记结果如何,或者抛出异常,最后都要释放资源解锁
}
public void out()throws InterruptedException
{
try
{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
condition_pro.signal();
}
finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private Resource res;
Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.set("+商品+");
}
catch (InterruptedException e)
{
}
}
}
}
class Consumer implements Runnable
{
private Resource res;
Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
try
{
res.out();
}
catch (InterruptedException e)
{
}
}
}
}
class ProducerConsumerDemo
{
public static void main(String[] args)
{
Resource r = new Resource();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t1 = new Thread(pro);//创建两个生产者线程和两个消费都线程
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
复制代码
作者:
孙飞
时间:
2012-7-5 20:08
feigecal 发表于 2012-7-5 08:06
因为每个线程的执行次数是不确定 的,面for循环一般是在明确循环次数的时候用比较合适,所以这里用while比 ...
不好意思啊,格式改好了
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2