黑马程序员技术交流社区
标题:
生产者消费者问题
[打印本页]
作者:
haozi050
时间:
2014-2-1 00:28
标题:
生产者消费者问题
本帖最后由 haozi050 于 2014-2-9 08:33 编辑
有一个很奇怪的问题,我照着视频写了生产者消费者代码,运行出结果了,但商品标记count没有一次是从1开始的.我运行了别人的正确代码也不是从1开始打印的,哪位大神能告诉我为什么吗?Thread-2..消费者..馒头50090
Thread-1..生产者..馒头50091
Thread-3..消费者..馒头50091
Thread-0..生产者..馒头50092
Thread-2..消费者..馒头50092
Thread-1..生产者..馒头50093
Thread-3..消费者..馒头50093
Thread-0..生产者..馒头50094
Thread-2..消费者..馒头50094
Thread-1..生产者..馒头50095
Thread-3..消费者..馒头50095
Thread-0..生产者..馒头50096
Thread-2..消费者..馒头50096
一开始就是50090,下面是代码:
import java.util.concurrent.locks.*;
//定义资源类
class OneResource
{
private String name;//名称
private int count=1;//编号
boolean flag=false;//标记
// 创建一个锁对象
Lock lock=new ReentrantLock();
// 创建两个监视器方法对象,一个监视生产者,一个监视消费者
Condition produce=lock.newCondition();
Condition consume=lock.newCondition();
public void set(String name)//定义生产馒头方法
{
// 上锁
lock.lock();
// 如果标记为假就进行生产否则就等待。由于会抛异常,防止异常之后没释放锁,要用try finally
try{
while(flag)
{try{produce.await();}catch(InterruptedException e){}}
this.name=name+count;
System.out.println(Thread.currentThread().getName()+"..生产者.."+this.name);
count++;
// 生产完之后将标记改为真,唤醒消费者线程。
flag=true;
consume.signal();
}
// 释放锁
finally{
lock.unlock();
}
}
public void get()//定义消费方法
{
lock.lock();
try{
// 如果标记为真则消费,否则等待
while(!flag)
{
{try{consume.await();}catch(InterruptedException e){}}
}
System.out.println(Thread.currentThread().getName()+"..消费者.."+this.name);
// 消费完之后将标记改为假,唤醒生产者
flag=false;
produce.signal();
}finally{
lock.unlock();
}
}
}
//定义生产者
class MoreProducer implements Runnable
{
// 为了保证资源一致,这里定义构造函数接受资源对象,一初始化时就有资源对象。
OneResource r;
MoreProducer(OneResource r)
{
this.r=r;
}
// 明确生产者的任务,生产馒头
public void run()
{
// 一直生产
while(true)
r.set("馒头");
}
}
//定义消费者类
class MoreConsumer implements Runnable
{
// 一初始化也要有统一的资源对象
OneResource r;
MoreConsumer(OneResource r)
{
this.r=r;
}
// 明确消费者的消费任务
public void run()
{
// 一直消费
while(true)
r.get();
}
}
public class ProducerConsumerFinal {
public static void main(String[] args) {
//创建资源对象,并将资源传递给生产者消费者
// 创建任务对象即生产任务和消费任务,生产任务和消费任务都只有一个
OneResource r=new OneResource();
MoreProducer p1=new MoreProducer(r);
MoreConsumer c1=new MoreConsumer(r);
// 创建线程并指定线程任务
Thread t0=new Thread(p1);
Thread t1=new Thread(p1);
Thread t2=new Thread(c1);
Thread t3=new Thread(c1);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
复制代码
作者:
e.c
时间:
2014-2-4 16:10
另一个贴里已经说了~
运行太快,记录太多把前面的覆盖了。
eclipse里可以通过:右键--run as--run configurations--里的common标签配置将结果输出到文件就可以看到了。
命令行可以通过 java ProducerConsumerFinal >>log.txt将结果输出到当前工作目录的log.txt文件。以方便查看。
另建议运行后立马停止。不然记录太多打开会很卡
作者:
e.c
时间:
2014-2-4 16:17
e.c 发表于 2014-2-4 16:10
另一个贴里已经说了~
运行太快,记录太多把前面的覆盖了。
eclipse里可以通过:右键--run as--run configur ...
或者让生产消费后线程sleep(500)休眼一会儿就可以看到了
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2