美文网首页
生产者-消费者问题

生产者-消费者问题

作者: 秋笙fine | 来源:发表于2019-01-26 13:17 被阅读0次

1.生产者-消费者问题的产生

生产者和消费者指的是两个不同的线程类对象,操作同一资源的情况。具体操作情况如下。

1.生产者负责生产数据,消费者负责取走数据
2.生产者每生产完一组数据之后,消费者就要取走一组数据

第一组数据:title="sl",content="Good Student"
第二组数据:title=“动物”,content="sheep"

package TestDemo;

class Info{
    String name;
    String content;
    /**
     * @return the content
     */
    public String getContent() {
        return content;
    }
    /**
     * @param content the content to set
     */
    public void setContent(String content) {
        this.content = content;
    }
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }
}
class Productor implements Runnable{
    private Info info;
    public Productor(Info info){
        this.info=info;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            if(i%2==0){
                this.info.setName("animal");
                try {
                    Thread.sleep(100);

                } catch (Exception e) {
                    //TODO: handle exception
                }
                this.info.setContent("sheep");
                continue;
            }
            this.info.setName("sl");
            try {
                Thread.sleep(100);

            } catch (Exception e) {
                //TODO: handle exception
            }
            this.info.setContent("Good student");
        }
        
    }
}

class Customer implements Runnable{
    private Info info;
    public Customer(Info info){
        this.info=info;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);

            } catch (Exception e) {
                //TODO: handle exception
            }
            System.out.println(this.info.getName()+"===="+this.info.getContent());
        }
    }
}

public class TestDemo{
    
    public static void main(String[] args){
     Info info=new Info();
     new Thread(new Productor(info)).start();//由于生产者消费者类都是Runnable子类,可以传入构造
     new Thread(new Customer(info)).start();
    }   
}

结果


image.png image.png

发现了两个严重问题:
1.数据错位
2.数据重复取出,数据重复设置

1.解决数据错位问题
数据错位完全是因为非同步的操作所造成的,所以应该使用同步处理。并且两个数据要同时设置。同时取出。因而对set,get进行同步方法

package TestDemo;

class Info{
    String name;
    String content;
    public synchronized void set(String name,String content){
        this.name=name;
        try {
            Thread.sleep(200);

        } catch (Exception e) {
            //TODO: handle exception
        }
        this.content=content;
    }
    public synchronized void get(){
        try {
            Thread.sleep(100);
        } catch (Exception e) {
            //TODO: handle exception
        }
        System.out.println(this.name+"==="+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 < 10; i++) {
            if(i%2==0){
                this.info.set("animal", "sheep");
                continue;
            }
            this.info.set("sl", "Good student");
        }
        
    }
}

class Customer implements Runnable{
    private Info info;
    public Customer(Info info){
        this.info=info;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
        
            this.info.get();
        }
    }
}

public class TestDemo{
    
    public static void main(String[] args){
     Info info=new Info();
     new Thread(new Productor(info)).start();//由于生产者消费者类都是Runnable子类,可以传入构造
     new Thread(new Customer(info)).start();
    }
}

此时,数据错位问题得到了解决,但是重复问题更加严重了。


image.png

然后我们解决重复问题:
如果要想实现整个代码的操作,必须加入等待与唤醒机制,在Object类里面有专门的处理方法

2.Object类对多线程的支持

Object类中有如下方法:
等待:public final void wait() throws InterruptedException
唤醒第一个等待线程:public final void notify();
唤醒全部等待线程,哪个优先级高,唤醒哪个:
public final void notifyAll();

解决重复问题:修改info方法

package TestDemo;

class Info{
    String name;
    String content;
    private boolean flag=true;
    //flag为true表示可以生产,但是不能取走
    //flag为false表示可以取走但是不能生产
    public synchronized void set(String name,String content){
        //如果重复进行set方法
        if(this.flag==false){
            try {
                super.wait();//让线程等待
            } catch (Exception e) {
                //TODO: handle exception
            }
            
        }

        this.name=name;
        try {
            Thread.sleep(200);

        } catch (Exception e) {
            //TODO: handle exception
        }
        this.content=content;
        this.flag=false;//修改生产标记
        super.notify();//唤醒其它等待线程
    }
    public synchronized void get(){
        if(this.flag==true){
            try {
                super.wait();
            } catch (Exception e) {
                //TODO: handle exception
            }
        }
        try {
            Thread.sleep(100);
        } catch (Exception e) {
            //TODO: handle exception
        }
        System.out.println(this.name+"==="+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 < 10; i++) {
            if(i%2==0){
                this.info.set("animal", "sheep");
                continue;
            }
            this.info.set("sl", "Good student");
        }
        
    }
}

class Customer implements Runnable{
    private Info info;
    public Customer(Info info){
        this.info=info;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
        
            this.info.get();
        }
    }
}

public class TestDemo{
    
    public static void main(String[] args){
     Info info=new Info();
     new Thread(new Productor(info)).start();//由于生产者消费者类都是Runnable子类,可以传入构造
     new Thread(new Customer(info)).start();
    }   
}
image.png

成功了。

面试题:请解释sleep与wait区别:
sleep()是Thread类定义的方法,wait()是Object类定义的方法
sleep()可以设置休眠时间,时间一到自动唤醒,wait需要notify方法来唤醒。

总结

生产者-消费者模型是一个非常经典的多线程处理模型。

相关文章

  • 生产者和消费者问题

    生产者和消费者问题 问题简述 组成 系统中有一组生产者和消费者进程 生产者生产者将产品放入缓冲区 消费者消费者进程...

  • 操作系统知识点持续更新

    生产者消费者问题 关于生产者消费者问题可以参考这篇文章:生产者消费者问题的java实现 临界区与互斥量 临界区:保...

  • 经典同步互斥问题

    生产者消费者问题 生产者消费者应当是最最基本的同步互斥问题了。生产者生产了之后消费者才消费,消费者消费之后,通知生...

  • 生产者和消费者问题详解

    生产者和消费者问题详解 定义 生产者消费者问题(英语:Producer-consumer problem),也称有...

  • 2-1.死锁-经典同步问题

    三、经典同步问题 1.生产者-消费者问题 计算机系统中的许多问题都可归结为生产者与消费者问题,生产者与消费者可以通...

  • 9. python多进程之Queue实现生产者消费者模型

    一、概述 什么是生产者消费者模式生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此...

  • 生产者消费者

    什么是生产者和消费者 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。 生产者和消费者彼此之间不直...

  • java生产者消费者实现

    什么是生产者消费者模式 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直...

  • 生产者消费者模式-java原生、Disruptor实现方案

    生产者消费者模式介绍 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接...

  • Java实现生产者-消费者模型的几种方法

    什么是生产者消费者模式 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直...

网友评论

      本文标题:生产者-消费者问题

      本文链接:https://www.haomeiwen.com/subject/mzqpjqtx.html