多线程生产者与消费者简单模拟

生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。

情形一:简单模型,生产者产生一个,消费者拿一个。

class Q{
    private int n;
    private boolean valueSet=false;
    public Q(int n){
        this.n=n;
    }
    public Q(){}
    public synchronized void add() throws InterruptedException {
        if(valueSet){
            wait();
        }
        valueSet=true;
        n++;
        System.out.println("have:"+n +" "+"增加一个");
        notify();
    }
    public synchronized int move() throws InterruptedException {
        if(!valueSet){
            wait();
        }
        n--;
        System.out.println("have:"+n+" "+"减少一个");
        valueSet=false;
        notify();
        return this.n;
    }
}
public class Customer implements Runnable{
    Q q;
    public Customer(Q q){
        this.q=q;
        new Thread(this,"Customer").start();
    }
    @Override
    public void run() {
        while(true){
            try {
                q.move();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Product implements Runnable{
    Q q;
    public Product(Q q){
        this.q=q;
        new Thread(this,"Product").start();
    }
    @Override
    public void run() {
        int i=0;
        while (true){
            try {
                q.add();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public static void main(String[] args) throws InterruptedException {
        Q q=new Q(1);
        Product p=new Product(q);
        Customer c=new Customer(q);
}

输出:
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个
have:2 增加一个
have:1 减少一个

情形二:多个消费者多个生产者

import java.util.List;

public class  CustomerPlus implements Runnable{
    private Listlist;
    public CustomerPlus(){};
    public CustomerPlus(Listlist){
        this.list=list;
    }
    @Override
    public void run() {
        while (true) {
            synchronized (list) {
                int n=list.size();
                if (n > 0) {
                    list.remove(n-1);
                    System.out.println("消费一个 "+"当前数量为:"+list.size());
                }
                list.notifyAll();
                try {
                    Thread.sleep(100);
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}
class ProductPlus implements Runnable{
    private Listlist;
    public ProductPlus(){}
    public ProductPlus(Listlist){
        this.list=list;
    }
    @Override
    public void run() {
        while (true) {
            synchronized (list) {
                if (list.size() < 20) {
                    list.add(1);
                    System.out.println("生产一个 "+"当前数量为:"+list.size());
                }
                list.notifyAll();
                try {
                    Thread.sleep(100);
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}
public static void main(String[] args) throws InterruptedException {
     Listlist=new ArrayList<>(20);
        list.add(1);
        list.add(1);
        ProductPlus p1=new ProductPlus(list);
        ProductPlus p2=new ProductPlus(list);
        ProductPlus p3=new ProductPlus(list);
        CustomerPlus c1=new CustomerPlus(list);
        CustomerPlus c2=new CustomerPlus(list);
        Thread t1=new Thread(p1);
        t1.start();
        Thread.sleep(100);
        Thread t2=new Thread(p2);
        t2.start();
        Thread.sleep(100);
        Thread t3=new Thread(p3);
        t3.start();
        Thread.sleep(100);
        Thread t4=new Thread(c1);
        t4.start();
        Thread.sleep(100);
        Thread t5=new Thread(c2);
        t5.start();
        Thread.sleep(100);
}

运行结果:
生产一个 当前数量为:3
生产一个 当前数量为:4
生产一个 当前数量为:5
生产一个 当前数量为:6
生产一个 当前数量为:7
消费一个 当前数量为:6
生产一个 当前数量为:7
生产一个 当前数量为:8
消费一个 当前数量为:7
生产一个 当前数量为:8
生产一个 当前数量为:9
生产一个 当前数量为:10
消费一个 当前数量为:9
生产一个 当前数量为:10
生产一个 当前数量为:11
消费一个 当前数量为:10
生产一个 当前数量为:11
消费一个 当前数量为:10
生产一个 当前数量为:11
生产一个 当前数量为:12
消费一个 当前数量为:11
生产一个 当前数量为:12
生产一个 当前数量为:13
生产一个 当前数量为:14
消费一个 当前数量为:13
生产一个 当前数量为:14
生产一个 当前数量为:15
消费一个 当前数量为:14
生产一个 当前数量为:15
消费一个 当前数量为:14
生产一个 当前数量为:15
生产一个 当前数量为:16
消费一个 当前数量为:15
生产一个 当前数量为:16
生产一个 当前数量为:17
生产一个 当前数量为:18
消费一个 当前数量为:17
生产一个 当前数量为:18
生产一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
生产一个 当前数量为:20
消费一个 当前数量为:19
消费一个 当前数量为:18
生产一个 当前数量为:19
生产一个 当前数量为:20

你可能感兴趣的:(java,多线程)