线程操作案例----生产者和消费者

  既然现在的是信息,所以就可以定义一个信息的表示类,生产者和消费者都同时占有这个信息类的引用,那么,就可以将生产者和消费者两个线程通过信息类联合在一起。

  建立生产者类,生产者实现多线程机制。生产者生产50此信息,中间为了更好的发现问题,加入了延迟操作。

  实现消费者,消费者要不断的取出。

class Info{    // 定义信息类
    private String name = "李兴华";     // 定义name属性
    private String content = "JAVA讲师"  ;        // 定义content属性
    public void setName(String name){
        this.name = name ;
    }
    public void setContent(String content){
        this.content = content ;
    }
    public String getName(){
        return this.name ;
    }
    public String getContent(){
        return this.content ;
    }
};
class Producer implements Runnable{    // 生产者,通过Runnable实现多线程
    private Info info = null ;        // 保存Info引用
    public Producer(Info info){
        this.info = info ;
    }
    public void run(){
        boolean flag = false ;    // 定义标记位
        for(int i=0;i<50;i++){
            if(flag){
                this.info.setName("李兴华") ;    // 设置名称
                try{
                    Thread.sleep(90) ;
                }catch(InterruptedException e){
                    e.printStackTrace() ;
                }
                this.info.setContent("JAVA讲师") ;    // 设置内容
                flag = false ;
            }else{
                this.info.setName("mldn") ;    // 设置名称
                try{
                    Thread.sleep(90) ;
                }catch(InterruptedException e){
                    e.printStackTrace() ;
                }
                this.info.setContent("www.mldnjava.cn") ;    // 设置内容
                flag = true ;
            }
        }
    }
};
class Consumer implements Runnable{    //消费者    
    private Info info = null ;
    public Consumer(Info info){
        this.info = info ;
    }
    public void run(){
        for(int i=0;i<50;i++){
            try{
                Thread.sleep(90) ;
            }catch(InterruptedException e){
                e.printStackTrace() ;
            }
            System.out.println(this.info.getName() + 
                " --> " + this.info.getContent()) ;
        }
    }
};
public class ThreadCaseDemo01{
    public static void main(String args[]){
        Info info = new Info();    // 实例化Info对象
        Producer pro = new Producer(info) ;    // 生产者
        Consumer con = new Consumer(info) ;    // 消费者
        new Thread(pro).start() ;
        new Thread(con).start() ;
    }
};
View Code

通过测试代码来发现程序的问题:

李兴华 --> www.mldnjava.cn
李兴华 --> www.mldnjava.cn
李兴华 --> www.mldnjava.cn
mldn --> JAVA讲师
李兴华 --> www.mldnjava.cn
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
mldn --> JAVA讲师
mldn --> JAVA讲师
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
李兴华 --> www.mldnjava.cn
李兴华 --> www.mldnjava.cn
......

之所以会出现内容不对应的情况,是因为中间加入了延迟操作,所以有可能产生不同步的问题,可以使用同步解决设置内容问题。

class Info{    // 定义信息类
    private String name = "李兴华";     // 定义name属性
    private String content = "JAVA讲师"  ;        // 定义content属性
    public synchronized void set(String name,String content){
        this.setName(name) ;    // 设置名称
        try{
            Thread.sleep(300) ;
        }catch(InterruptedException e){
            e.printStackTrace() ;
        }
        this.setContent(content) ;    // 设置内容
    }
    public synchronized void get(){
        try{
            Thread.sleep(300) ;
        }catch(InterruptedException e){
            e.printStackTrace() ;
        }
        System.out.println(this.getName() + 
            " --> " + this.getContent()) ;
    }
    public void setName(String name){
        this.name = name ;
    }
    public void setContent(String content){
        this.content = content ;
    }
    public String getName(){
        return this.name ;
    }
    public String getContent(){
        return this.content ;
    }
};
class Producer implements Runnable{    // 通过Runnable实现多线程
    private Info info = null ;        // 保存Info引用
    public Producer(Info info){
        this.info = info ;
    }
    public void run(){
        boolean flag = false ;    // 定义标记位
        for(int i=0;i<50;i++){
            if(flag){
                this.info.set("李兴华","JAVA讲师") ;    // 设置名称
                flag = false ;
            }else{
                this.info.set("mldn","www.mldnjava.cn") ;    // 设置名称
                flag = true ;
            }
        }
    }
};
class Consumer implements Runnable{
    private Info info = null ;
    public Consumer(Info info){
        this.info = info ;
    }
    public void run(){
        for(int i=0;i<50;i++){
            this.info.get() ;
        }
    }
};
public class ThreadCaseDemo02{
    public static void main(String args[]){
        Info info = new Info();    // 实例化Info对象
        Producer pro = new Producer(info) ;    // 生产者
        Consumer con = new Consumer(info) ;    // 消费者
        new Thread(pro).start() ;
        new Thread(con).start() ;
    }
};
View Code
mldn --> www.mldnjava.cn
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
李兴华 --> JAVA讲师
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
mldn --> www.mldnjava.cn
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
mldn --> www.mldnjava.cn
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
李兴华 --> JAVA讲师
......

以上代码解决了数据的完整性问题,但依旧存在重复取的问题,既然有重复取,则肯定有重复设置的问题。

要达到设置一个取走一个的功能要求,如果想要采用以上的一种机制,则必须依靠Object类中的方法支持。

 

直接修改Info类即可增加等待与唤醒的机制

class Info{    // 定义信息类
    private String name = "李兴华";     // 定义name属性
    private String content = "JAVA讲师"  ;        // 定义content属性
    private boolean flag = false ;    // 设置标志位
    public synchronized void set(String name,String content){
        if(!flag){
            try{
                super.wait() ;
            }catch(InterruptedException e){
                e.printStackTrace() ;
            }
        }
        this.setName(name) ;    // 设置名称
        try{
            Thread.sleep(300) ;
        }catch(InterruptedException e){
            e.printStackTrace() ;
        }
        this.setContent(content) ;    // 设置内容
        flag  = false ;    // 改变标志位,表示可以取走
        super.notify() ;
    }
    public synchronized void get(){
        if(flag){
            try{
                super.wait() ;
            }catch(InterruptedException e){
                e.printStackTrace() ;
            }
        }
        try{
            Thread.sleep(300) ;
        }catch(InterruptedException e){
            e.printStackTrace() ;
        }
        System.out.println(this.getName() + 
            " --> " + this.getContent()) ;
        flag  = true ;    // 改变标志位,表示可以生产
        super.notify() ;
    }
    public void setName(String name){
        this.name = name ;
    }
    public void setContent(String content){
        this.content = content ;
    }
    public String getName(){
        return this.name ;
    }
    public String getContent(){
        return this.content ;
    }
};
class Producer implements Runnable{    // 通过Runnable实现多线程
    private Info info = null ;        // 保存Info引用
    public Producer(Info info){
        this.info = info ;
    }
    public void run(){
        boolean flag = false ;    // 定义标记位
        for(int i=0;i<50;i++){
            if(flag){
                this.info.set("李兴华","JAVA讲师") ;    // 设置名称
                flag = false ;
            }else{
                this.info.set("mldn","www.mldnjava.cn") ;    // 设置名称
                flag = true ;
            }
        }
    }
};
class Consumer implements Runnable{
    private Info info = null ;
    public Consumer(Info info){
        this.info = info ;
    }
    public void run(){
        for(int i=0;i<50;i++){
            this.info.get() ;
        }
    }
};
public class ThreadCaseDemo03{
    public static void main(String args[]){
        Info info = new Info();    // 实例化Info对象
        Producer pro = new Producer(info) ;    // 生产者
        Consumer con = new Consumer(info) ;    // 消费者
        new Thread(pro).start() ;
        new Thread(con).start() ;
    }
};
View Code
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
mldn --> www.mldnjava.cn
李兴华 --> JAVA讲师
......

 

posted @ 2015-03-16 11:57  闲来垂钓  阅读(146)  评论(0)    收藏  举报