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

来源:互联网 发布:淘宝可以刷信用卡吗 编辑:程序博客网 时间:2024/06/05 15:53

举例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()进行唤醒。
0 0
原创粉丝点击