黑马程序员技术交流社区
标题:
自己写的生产者消费者,运行异常,求帮手解决它,谢谢。
[打印本页]
作者:
墨香
时间:
2014-5-17 13:44
标题:
自己写的生产者消费者,运行异常,求帮手解决它,谢谢。
import java.util.concurrent.locks.*;
class goods
{
int num=0;
String name;
boolean flag=false;
public void set(String name)
{
this.name=name;
num++;
System.out.println(Thread.currentThread().getName()+"生产第"+num+"件"+name);
}
public void show()
{
System.out.println(Thread.currentThread().getName()+"消费第"+num+"件"+name);
}
}
class Producer implements Runnable
{
Lock lock=new ReentrantLock();
Condition condition=lock.newCondition();
goods g;
Producer(goods g)
{
this.g=g;
}
public void run()
{
lock.lock();
while(true)
{
try
{
while(g.flag)
condition.await();
if(g.flag)
g.set("商品");
g.flag=true;
condition.signalAll();
}
finally
{
lock.unlock();
}
}
}
}
class Customer implements Runnable
{
goods g;
Lock lock=new ReentrantLock();
Condition condition=lock.newCondition();
Customer(goods g)
{
this.g=g;
}
public void run()
{
lock.lock();
while(true)
{
try
{
while(!g.flag)
condition.await();
if(g.flag)
g.set("商品");
g.flag=false;
condition.signalAll();
}
finally
{
lock.unlock();
}
}
}
}
class ProducerCustomer
{
public static void main(String[] args)
{
goods g=new goods();
new Thread(new Producer(g)).start();
new Thread(new Customer(g)).start();
}
}
作者:
lzhuas
时间:
2014-5-17 14:14
我帮你找个小问题,你卖东西了吗?其他的自己好好调试调试,我就不帮你了
作者:
海世山盟
时间:
2014-5-17 19:48
首先是异常处理 有重大错误, catch 是必须有的,一个或者多个。没有catch 怎么处理异常呢?
其他应该没什么问题。
作者:
۩大世界小人物
时间:
2014-5-17 20:11
缺少catch (InterruptedException e){} 而且整个代码不完整,都没法给你调
作者:
۩大世界小人物
时间:
2014-5-17 20:13
本帖最后由 ۩大世界小人物 于 2014-5-17 21:08 编辑
<p>package testSingle;</p><p>import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;</p><p>/*
* 生产者和消费者:
*
* jdk1.5以后将同步和锁封装成了对象。并将操作锁的隐式方式定义到了该对象中。将隐式动作变成了显示动作。*******************
*/</p><p>class Resrouce
{
private String name;
private int count = 1;
private boolean flag = false;
Lock lock = new ReentrantLock();//定义一把锁
//通过已有的锁 获取该锁上的监视器对象。
Condition con = lock.newCondition();
public void set(String name)
{
lock.lock();//获取一把锁
try
{
while(flag)
{
try
{
con.await();
}
catch (InterruptedException e)
{
// TODO: handle exception
}
}
this.name = name + count;
count++;
System.out.println(Thread.currentThread().getName()+"....生产者。。。。"+this.name);
flag = true;
con.signalAll();
}
catch (Exception e)
{
// TODO: handle exception
}
finally
{
lock.unlock();
}
}
public void out()
{
lock.lock();//获取锁
try
{
while(!flag)
{
try
{
con.await();
}
catch (InterruptedException e)
{
// TODO: handle exception
}
}
System.out.println(Thread.currentThread().getName()+"-----------------消费者-"+ this.name);
flag = false;
con.signalAll();
}
catch (Exception e)
{
// TODO: handle exception
}
finally
{
lock.unlock();
}
}
}
//生产者
class Producer implements Runnable
{
private Resrouce r;
Producer(Resrouce r)
{
this.r = r;
}</p><p> @Override
public void run()
{
// TODO Auto-generated method stub
while(true)
r.set("馒头");
}
}
//消费者
class Consumer implements Runnable
{
private Resrouce r;
Consumer(Resrouce r)
{
this.r = r;
}</p><p> @Override
public void run()
{
// TODO Auto-generated method stub
while(true)
r.out();
}
}
public class ResourceTest
{</p><p> /**
* @param args
*/
public static void main(String[] args)
{
// TODO Auto-generated method stub
Resrouce r = new Resrouce();
Consumer c1 = new Consumer(r);
Consumer c2 = new Consumer(r);
Producer p1 = new Producer(r);
Producer p2 = new Producer(r);
Thread t1 = new Thread(p1);
t1.start();
Thread t2 = new Thread(p2);
t2.start();
Thread t3 = new Thread(c1);
t3.start();
Thread t4 = new Thread(c2);
t4.start();</p><p> }</p><p>}</p><p>
</p>
复制代码
可以对照一下这个消费者线程安全问题
作者:
pandapan
时间:
2014-5-17 21:26
本帖最后由 pandapan 于 2014-5-17 21:28 编辑
这位同学,应该是刚接触java吧。下面我把这个里面的存在的目前发现的问题列举出来
1. 你的这段代码应该是没有编译过的吧,或者说只是用UE或者EditPlus编写的,一般情况下我们是不直接写try finally代码的,这样是完全没有异常处理的代码的,那么就算有异常,我们是怎么发现的呢?
2. 类的命名不符合规则,货物类单词拼写的是对的,goods,但是记得要大写的,童鞋。应该是Goods(不要小瞧这些细节,面试的时候,假如面试官看你写这样的代码,会很生气的,因为有通用的规则,大家都是遵守的,凭什么我们例外的?)
3.需求理解有一定的偏差,或者说理解了需求,实现的有偏差。通过浏览你的代码,我是否可以反推出这样的需求呢?
3.1 业务背景
在日常生活中呢,很普通的一个事情就是生产者和消费者的故事了,生产者负责生产,消费者负责消费,生产和消费的是随机的,就是生产者生产一个后,便开始停工,等着消费者完成后再继续生产。请模拟这样的过程。
3.2 需求分析
看到这个问题,我们分析的结果如下,生产者呢,负责生产商品,消费者呢,负责消费商品,这是不同的操作,却要同时进行,因而考虑使用多线程,在取的过程和消费的过程可能会发生冲突,因而考虑到要加锁。这是大概的设计。由于生产者生产了一个后,便停用,等着消费者消费,便没有商品的多少和商品的队列的信息的维护,我们用一个标记(Flag)描述即可.3.3 设计(这里的设计我就不怎么说了,因为楼主设计的整体思路应该是有的,但是感觉是缺乏基本知识的理解)
设计呢,首先便要知道多线程的基本知识,
(1)在不同的线程中加锁呢,要加同样的锁,如果锁不同的话,那么加锁就没有意义了,楼主这里在生产者和消费者中使用了不同的锁,因为都是在自己的类中创立的,因而有Lock创建的Condition肯定也是有问题的。
你的代码我进行了如下的改进,可以运行了,希望能够帮到你.希望楼主能够先学习学习同步代码块的知识,这样再学习Lock和Condition的知识会很快的。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ProducerCustomer {
public static void main(String[] args) {
// TODO Auto-generated method stub
Goods good = new Goods();
new Thread(new Consumer(good)).start();
new Thread(new Producer(good)).start();
}
}
/**
* 生产者
* @author Panda
*
*/
class Producer implements Runnable{
Goods good = null;
public Producer(Goods good){
this.good = good;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
LockInstance.lockEg.lock();
try {
while(good.flag){//true的时候不生产
LockInstance.proCondtion.await();
}
good.set("商品");
good.flag = true;
LockInstance.conCondtion.signal();
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
LockInstance.lockEg.unlock();
}
}
}
}
/**
* 消费者
* @author Panda
*
*/
class Consumer implements Runnable{
Goods good = null;
public Consumer(Goods good){
this.good = good;
}
@Override
public void run() {
while(true){
LockInstance.lockEg.lock();
try {
while(!good.flag){
LockInstance.conCondtion.await();
}
good.show();
good.flag = false;
LockInstance.proCondtion.signal();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
LockInstance.lockEg.unlock();
}
}
}
}
/**
* 所有相关的锁的相关实例,为了方便操作,因而全部采用共有
* @author Panda
*
*/
class LockInstance{
public static Lock lockEg = new ReentrantLock();
public static Condition proCondtion = lockEg.newCondition();//生产者条件
public static Condition conCondtion = lockEg.newCondition();//消费者条件
}
class Goods{
int num = 0;
String name;
boolean flag = false;//为
/**
* 模拟生产商品
*/
public void set(String name){
this.name=name;
num++;
System.out.println(Thread.currentThread().getName()+"生产第"+num+"件"+name);
}
/**
* 模拟消费商品
*/
public void show(){
System.out.println(Thread.currentThread().getName()+"消费第"+num+"件"+name);
}
}
复制代码
作者:
大漠孤烟
时间:
2014-5-17 23:49
楼上的总结好详细啊,复习啦、、、、
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2