首页 新闻 搜索 专区 学院

java多线程通信问题

0
悬赏园豆:40 [待解决问题]

我把线程同步和线程通信的代码在生产者内部实现时可以正常避免多次生产和消费问题,但将线程同步和通信的代码封装在Queue中,却不能实现,请大家帮忙看一下。

代码一:没有将实现同步和线程通信的代码封装在Queue中

class Queue{
    String name;  
    char sex; 
    boolean isFull;
    public Queue(String name,char sex,boolean isFull){
        this.name=name;
        this.isFull=isFull;
        this.sex=sex;
    }
    public void put(String name,char sex){
        this.name=name;
        try{Thread.sleep(100);}catch(Exception e){}
        this.sex=sex;
    }
    public void get(){
        System.out.println(this.name);
        try{Thread.sleep(10);}catch(Exception e){}
        System.out.println(this.sex);
    }
}
//消费者
class Consumer implements Runnable{
    Queue q;  //队列,用于在生产者和消费者之间传递数据
    
    public Consumer(Queue q){
        this.q=q;
    }
    @Override
    public void run(){
        while(true){
            synchronized (q) {  //为了实现生产者和消费者同步,使用同一个锁其标(实现线程之间的同步),加入线程之间的通信可以解决消费者和生产者之间多次取和多次读的问题
                if(q.isFull){
                    q.get(); q.isFull=false;
                    q.notify();
                }else{
                    try{q.wait();}catch(Exception e){}
                }
            } 
        }
    }
}

class Produce implements Runnable{
    Queue q;
    int i=1;
    public Produce(Queue q){
        this.q=q;  //接收从外部传来的参数,这样可以保证生产者和消费者操作同一个缓冲区
    }
    @Override
    public void run(){
        while(true){
            synchronized (q) {   
                if(!q.isFull){
                    if(i%2==0){
                        q.put("chejt",'m');
                    }else{
                        q.put("www",'f');
                    }
                    i++;
                    q.isFull=true;
                    q.notify();
                }else{
                    try{q.wait();}catch(Exception e){}
                }
                
            }
        }
    }
}

//测试类
public class ThreadCommunication{
    public static void main(String[] args){
        Queue q=new Queue("unkown",'u',false);
        Thread pro = new Thread(new Produce(q)); 
        Thread con = new Thread(new Consumer(q));
        pro.start();
        con.start();
    }
}

代码二:将实现同步与线程通信的代码封装在Queue中

class Queue{
    private String name;  
    private char sex; 
    private boolean isFull;
    public Queue(String name,char sex,boolean isFull){
        this.name=name;
        this.isFull=isFull;
        this.sex=sex;
    }
    public synchronized void put(String name,char sex){ 
        if(!isFull){
            this.name=name;
            //System.out.println("this name===================");
            try{
                Thread.sleep(10);
            //    System.out.println("sleep");
            }catch(Exception e){}
            //System.out.println("======================");
            this.sex=sex;
            this.isFull=true;
            notify();
        }else{
            //System.out.println("put wait===============");
            try{wait();}catch(Exception e){}
        }
    }
    public synchronized void get(){
        if(isFull){//为了实现生产者和消费者同步,使用同一个锁其标(实现线程之间的同步),加入线程之间的通信可以解决消费者和生产者之间多次取和多次读的问题
            //System.out.println("get ============");
            System.out.println(this.name);
            try{Thread.sleep(10);}catch(Exception e){}
            System.out.println(this.sex);
            this.isFull=false;
            notify();
        }else{
            //System.out.println("get ===========wait");
            try{wait();}catch(Exception e){}
        }
    }
}
//消费者
class Consumer implements Runnable{
    Queue q;  //队列,用于在生产者和消费者之间传递数据
    public Consumer(Queue q){
        this.q=q;
    }
    @Override
    public void run(){
        while(true){
            q.get(); 
        }
    }
}

class Produce implements Runnable{
    Queue q;
    int i=1;
    public Produce(Queue q){
        this.q=q;  //接收从外部传来的参数,这样可以保证生产者和消费者操作同一个缓冲区
    }
    @Override
    public void run(){
        while(true){
            //System.out.println("i=========="+i);
            if(i%2==0){
                q.put("chejt"+i,'m');
            }else{
                
                q.put("www"+i,'f');
            }
            i++;
        }
    }
}

//测试类
public class ThreadCommunication{
    public static void main(String[] args){
        System.out.println("main start");
        Queue q=new Queue("unkown",'u',false);
        Thread pro = new Thread(new Produce(q)); 
        Thread con = new Thread(new Consumer(q));
        pro.start();
        con.start();
    }
}
cjt1991的主页 cjt1991 | 初学一级 | 园豆:162
提问于:2014-09-29 09:40
< >
分享
所有回答(2)
0

Queue是将并行转变为串行,线程同步在队列里做?。。。,多次消费的问题一般是网络原因造成的吧,你这里是什么情况,没大明白,如果要实现生产者和消费者同步,用队列就不太合适了,队列就是为了异步提升吞吐量用的

draculav | 园豆:734 (小虾三级) | 2014-09-29 11:16

您好,谢谢你的解答。没有用队列,只是类名取得这样。它只是一个普通的类,里面存放名字和性别的普通类。

支持(0) 反对(0) cjt1991 | 园豆:162 (初学一级) | 2014-09-29 11:36
0

不是很懂,给你简单修改看:

//消费者
class Consumer implements Runnable{
    Queue q;  //队列,用于在生产者和消费者之间传递数据
    
    public Consumer(Queue q){
        this.q=q;
    }
    @Override
    public void run(){
        while(true){
            //增加这个循环,使得生产者有生产的机会
            while(q.isFull)
            {
                 thread.Sleep(100);
            }
            synchronized (q) {  //为了实现生产者和消费者同步,使用同一个锁其标(实现线程之间的同步),加入线程之间的通信可以解决消费者和生产者之间多次取和多次读的问题
                if(q.isFull){
                    q.get(); q.isFull=false;
                    q.notify();
                }else{
                    try{q.wait();}catch(Exception e){}
                }
            } 
        }
    }
}

class Produce implements Runnable{
    Queue q;
    int i=1;
    public Produce(Queue q){
        this.q=q;  //接收从外部传来的参数,这样可以保证生产者和消费者操作同一个缓冲区
    }
    @Override
    public void run(){
        while(true){
            //增加这个循环,使得消费者有消费的机会
            while(q.isFull)
            {
                 thread.Sleep(100);
            }
            synchronized (q) {   
                if(!q.isFull){
                    if(i%2==0){
                        q.put("chejt",'m');
                    }else{
                        q.put("www",'f');
                    }
                    i++;
                    q.isFull=true;
                    q.notify();
                }else{
                    try{q.wait();}catch(Exception e){}
                }
                
            }
        }
    }
}

我个人以为,你的代码问题是:一直陷入了消费或生产的死循环锁定中,使得生产或消费根本就没机会执行。通过我增加的一段循环,使得生产者或消费者能有机会进行生产与消费。

你可以测试下,这个我没实验(对java不懂)

519740105 | 园豆:5810 (大侠五级) | 2014-09-30 10:02
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册