生产者消费者模式的两个问题及其改进

举例1:

class Info{
    private String title;
    private String content;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}
class Productor implements Runnable{
    private  Info info;
    public Productor(Info info){
        this.info=info;
    }
    @Override
    public void run() {
        for (int i=0;i<100;i++){
            if (i%2==0){
                this.info.setTitle("生产者");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.info.setContent("   生产AAAAA");
            }else{
                this.info.setTitle("消费者");
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.info.setContent("   消费BBBBB");
            }
        }
    }
}
class Customer implements Runnable{
    private Info info;

    public Customer(Info info) {
        this.info = info;
    }

    @Override
    public void run() {
        for (int i=0;i<100;i++){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(this.info.getTitle()+"-"+this.info.getContent());
        }
    }
}
public class MyThread {
    public static void main(String[] args) {
        Info info=new Info();
        new Thread(new Productor(info)).start();
        new Thread(new Customer(info)).start();
    }

}
以上代码产生两个问题:1、数据错位,发现不再是一个所需要的完整数据;
2、数据重复取出,数据重复设置。
下面解决第一个问题:  数据错位问题
数据错位完全是因为非同步的操作所造成的,应该使用同步处理。
class Info{
    private String title;
    private String content;

    public synchronized void set(String title,String content) {
        this.title = title;
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.content = content;
    }
    public synchronized void get(){
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(this.title+"-"+this.content);
    }
}
class Productor implements Runnable{
    private  Info info;
    public Productor(Info info){
        this.info=info;
    }
    @Override
    public void run() {
        for (int i=0;i<100;i++){
            if (i%2==0){
                this.info.set("生产者","   生产AAAAA");
            }else{
                this.info.set("消费者","   消费BBBBB");
            }
        }
    }
}
class Customer implements Runnable{
    private Info info;

    public Customer(Info info) {
        this.info = info;
    }

    @Override
    public void run() {
        for (int i=0;i<100;i++){
            this.info.get();
        }
    }
}
public class MyThread {
    public static void main(String[] args) {
        Info info=new Info();
        new Thread(new Productor(info)).start();
        new Thread(new Customer(info)).start();
    }

}
此时 数据的错位问题很好的得到了解决,但是重复操作问题更加严重了。
要想实现整个代码的操作,必须加入等待与唤醒机制。在Object类里面提供有专门的解决方法。
等待:
public final void wait() throws InterruptedException;
唤醒第一个等待线程:
public final void notify();
唤醒全部等待线程,哪个优先级高就先执行:
public final void notifyAll();
package thread;

/**
 * Created by Saber on 2016/5/17.
 */
class Info{
    private String title;
    private String content;
    private boolean flag=true;
    //flag=true,表示可以生产,但是不能取走;
    //flag=flase,表示可以取走,但是不可以生产;
    public synchronized void set(String title,String content) {
        //重复进入到了set()方法里面,发现不能够生产,所以要等待
        if (flag==false){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.title = title;
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        this.content = content;
        this.flag=false;
        super.notify();
    }
    public synchronized void get(){
        if (flag==true){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(this.title+"-"+this.content);
        this.flag=true;
        super.notify();
    }
}
class Productor implements Runnable{
    private  Info info;
    public Productor(Info info){
        this.info=info;
    }
    @Override
    public void run() {
        for (int i=0;i<100;i++){
            if (i%2==0){
                this.info.set("生产者","   生产AAAAA");
            }else{
                this.info.set("消费者","   消费BBBBB");
            }
        }
    }
}
class Customer implements Runnable{
    private Info info;

    public Customer(Info info) {
        this.info = info;
    }

    @Override
    public void run() {
        for (int i=0;i<100;i++){
            this.info.get();
        }
    }
}
public class MyThread {
    public static void main(String[] args) {
        Info info=new Info();
        new Thread(new Productor(info)).start();
        new Thread(new Customer(info)).start();
    }

}
以上操作会使得程序变慢;
请解释sleep()与wait()的区别
sleep()是Thread类定义的方法,wait()是Object类定义的方法;
sleep()可以设置休眠时间,时间一到自动唤醒,而wait()需要等待notify()进行唤醒。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值