java语言实现生产者与消费者模型

文章目录

  • 1. wait()与notify()方法
    • 1.1 wait()方法
    • 1.2 wait(long time)
    • 1.3 notify()
    • 1.4 notifyAll()
  • 2. 生产者消费者模型
    • 2.1 一个生产者一个消费者
    • 2.1 多个生产者多个消费者
      • 2.1.1 多个生产者多个消费者(生产者生产一个商品)
      • 2.1.2 多个生产者多个消费者(生产者生产商品数量不固定)

1. wait()与notify()方法

1.1 wait()方法

wait()方法又叫痴汉方法,就是使线程停止运行,会释放对象锁

  1. wait()方法调用该方法后会使当前线程进行等待,并且将该线程置入锁对象的等待队列中,直到接到通知或者被中断为止。
  2. wait()方法只能在同步方法或者同步代码块中调用,如果调用wait()时没有适当的锁,会抛出异常。
  3. wait()方法执行后,当前线程释放锁,其他线程可以竞争该锁。
package 生产者消费者模型;
class MyThread implements Runnable{
    private String str = new String();
    @Override
    public void run() {
        synchronized(str){
            System.out.println("wait方法开始...");
            try {
                str.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait方法结束...");
        }
    }
}
public class Test {
    public static void main(String[] args){
        MyThread mt = new MyThread();
        Thread thread = new Thread(mt);
        thread.start();
    }
}

执行结果:
wait方法开始…

1.2 wait(long time)

如果到了预计时间还未被唤醒,线程将继续执行

package 生产者消费者模型;
class MyThread implements Runnable{
    private String str = new String();
    @Override
    public void run() {
        synchronized(str){
            System.out.println("wait方法开始...");
            try {
                //等待1s如果未被唤醒、线程继续执行
                str.wait(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait方法结束...");
        }
    }
}
public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyThread mt = new MyThread();
        Thread thread = new Thread(mt);
        thread.start();
    }
}

执行结果:
wait方法开始…
wait方法结束…
wait()之后线程继续执行有两种方法:

  1. 调用该对象的notify()方法
  2. 线程等待时调用interrupt()中断该线程
package 生产者消费者模型;
class MyThread implements Runnable{
    private String str = new String();
    @Override
    public void run() {
        synchronized(str){
            System.out.println("wait方法开始...");
            try {
                str.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait方法结束...");
        }
    }
}
public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyThread mt = new MyThread();
        Thread thread = new Thread(mt);
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
    }
}

java语言实现生产者与消费者模型_第1张图片

1.3 notify()

  1. notify()方法也 必须在同步方法或者同步代码块中调用,用来唤醒等待在该对象上的线程。如果有多个线程等待,则任意挑选一个唤醒。
  2. notify()方法执行后唤醒线程不会立刻释放对象锁,要等待唤醒线程全部执行完毕后才释放对象锁。
package 生产者消费者模型;
class MyThread implements Runnable{
    private Object object ;
    private boolean flag;

    public MyThread(Object object, boolean flag) {
        this.object = object;
        this.flag = flag;
    }
    public void waitMethod()
    {
        synchronized (object)
        {
            System.out.println("wait方法开始.."+Thread.currentThread().getName());
            try {
                object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait方法结束.."+Thread.currentThread().getName());
        }
    }
    public void notifyMethod()
    {
        synchronized (object)
        {
            System.out.println("notify方法开始..."+Thread.currentThread().getName());
            object.notify();
            System.out.println("notify方法结束..."+Thread.currentThread().getName());
        }
    }
    @Override
    public void run() {
        if(flag){
            waitMethod();
        }else{
            notifyMethod();
        }
    }
}
public class Test {
    public static void main(String[] args) throws InterruptedException {
        Object object = new Object();
        MyThread myThread1 = new MyThread(object,true);
        MyThread myThread2 = new MyThread(object,false);
        Thread waitThread1 = new Thread(myThread1,"等待线程");
        Thread notifyThread2 = new Thread(myThread2,"唤醒线程");
        waitThread1.start();
        Thread.sleep(1000);
        notifyThread2.start();
    }
}

执行结果:
wait方法开始…等待线程
notify方法开始…唤醒线程
notify方法结束…唤醒线程
wait方法结束…等待线程

1.4 notifyAll()

唤醒所有在该对象上的等待线程

package 生产者消费者模型;
class MyThread implements Runnable{
    private Object object ;
    private boolean flag;

    public MyThread(Object object, boolean flag) {
        this.object = object;
        this.flag = flag;
    }
    public void waitMethod()
    {
        synchronized (object)
        {
            System.out.println("wait方法开始.."+Thread.currentThread().getName());
            try {
                object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("wait方法结束.."+Thread.currentThread().getName());
        }
    }
    public void notifyMethod()
    {
        synchronized (object)
        {
            System.out.println("notify方法开始..."+Thread.currentThread().getName());
            object.notifyAll();
            System.out.println("notify方法结束..."+Thread.currentThread().getName());
        }
    }
    @Override
    public void run() {
        if(flag){
            waitMethod();
        }else{
            notifyMethod();
        }
    }
}
public class Test {
    public static void main(String[] args) throws InterruptedException {
        Object object = new Object();
        MyThread myThread1 = new MyThread(object,true);
        MyThread myThread2 = new MyThread(object,false);
       for(int i=0 ;i<10;i++)
       {
           Thread waitThreadi = new Thread(myThread1,"等待线程"+i);
           waitThreadi.start();
       }
        Thread notifyThread2 = new Thread(myThread2,"唤醒线程");
        Thread.sleep(1000);
        notifyThread2.start();
    }
}

执行结果:
wait方法开始…等待线程1
wait方法开始…等待线程0
wait方法开始…等待线程2
wait方法开始…等待线程5
wait方法开始…等待线程4
wait方法开始…等待线程3
wait方法开始…等待线程6
wait方法开始…等待线程9
wait方法开始…等待线程7
wait方法开始…等待线程8
notify方法开始…唤醒线程
notify方法结束…唤醒线程
wait方法结束…等待线程8
wait方法结束…等待线程7
wait方法结束…等待线程9
wait方法结束…等待线程6
wait方法结束…等待线程3
wait方法结束…等待线程4
wait方法结束…等待线程5
wait方法结束…等待线程2
wait方法结束…等待线程0
wait方法结束…等待线程1

2. 生产者消费者模型

生产者与消费者模型一共有三种关系:生产者与生产者的互斥关系,消费者与消费者的互斥关系,生产者与消费者的互斥且同步关系。

2.1 一个生产者一个消费者

package 生产者消费者模型;
//货物类
class Goods {
    private String goods;
    private int count;
    public Goods(String goods) {
        this.goods = goods;
    }

    /**
     * 生产者生产货物的方法
     */
    public synchronized void produce(){
        if(count > 0){
            System.out.println("该商品还有库存....");
            //生产者等待
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果没有库存 商品数量+1
        this.count++;
        System.out.println(Thread.currentThread().getName()+"生产产品"+toString());
        //唤醒消费者
        notify();
    }

    /**
     * 消费者消费商品
     */
    public synchronized void consumer(){
        //防止消费者线程先启动 造成count称为负数
        if(count == 0){
            System.out.println("仓库已kong...");
            //消费者等待
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //消费商品 数量-1
        this.count--;
        System.out.println(Thread.currentThread().getName()+"消费产品"+toString());
         //唤醒生产者
        notify();
    }

    @Override
    public String toString() {
        return "Goods{" +
                "goods='" + goods + '\'' +
                ", count=" + count +
                '}';
    }
}
//生产者线程
class Producer implements Runnable{
    //生产的货物
    private Goods good;

    public Producer(Goods good) {
        this.good = good;
    }

    @Override
    public void run() {
        this.good.produce();
    }
}
//消费者线程
class Consumer implements Runnable{
    //消费的货物
    private Goods good;

    public Consumer(Goods good) {
        this.good = good;
    }

    @Override
    public void run() {
        this.good.consumer();
    }
}
public class Test{
    public static void main(String[] args) {

       Goods goods = new Goods("特百惠杯子");

       Producer producer = new Producer(goods);
       Consumer consumer = new Consumer(goods);

       Thread producerThread = new Thread(producer,"生产者");
       Thread consumerThread = new Thread(consumer,"消费者");

       consumerThread.start();
       producerThread.start();

    }
}

在这里插入图片描述
现实生活中肯定不是只存在一个生产者和一个消费者,生产者生产商品也肯定不是只生产一个,所以有多个生产者多个消费者的情况

2.1 多个生产者多个消费者

2.1.1 多个生产者多个消费者(生产者生产一个商品)

package 生产者消费者模型;

import java.util.ArrayList;
import java.util.List;

//货物类
class Goods {
    private String goods;
    private int count;
    public Goods(String goods) {
        this.goods = goods;
    }

    /**
     * 生产者生产货物的方法
     */
    public synchronized void produce(){
        //不断判断执行条件
        /**
         * 因为有多个线程 假设现在已有商品,生产者线程均在等待
         * 消费者线程唤醒生产者线程后,假设此时生产者线程1生产产品
         * 此时count=1,若用if判断会造成count数量一直增加
         */
        while(count > 0){
            System.out.println("该商品还有库存....");
            //生产者等待
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //如果没有库存 商品数量+1
        this.count++;
        System.out.println(Thread.currentThread().getName()+"生产产品"+toString());
        //唤醒所有消费者
        notifyAll();
    }

    /**
     * 消费者消费商品
     */
    public synchronized void consumer(){
        //不断判断执行条件
         /**因为有多个线程 假设消费者线程先执行、由于不止一个消费者
          * 此时可能有多个消费者在等待,如果此时一个生产者生产了商品
          * 消费者线程均被唤醒、如果此时线程2消费产品 此时若用if判断
          * 其余等待线程也会count-- 造成错误 所以需要用while判断
         */
        while(count == 0){
            System.out.println("仓库已空...");
            //消费者等待
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //消费商品 数量-1
        this.count--;
        System.out.println(Thread.currentThread().getName()+"消费产品"+toString());
        //唤醒所有生产者
        notifyAll();
    }

    @Override
    public String toString() {
        return "Goods{" +
                "goods='" + goods + '\'' +
                ", count=" + count +
                '}';
    }
}
//生产者线程
class Producer implements Runnable{
    //生产的货物
    private Goods goods;

    public Producer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        while(true){
            this.goods.produce();
        }
    }
}
//消费者线程
class Consumer implements Runnable{
    //消费的货物
    private Goods goods;

    public Consumer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        while(true){
            this.goods.consumer();
        }
    }
}
public class Test{
    public static void main(String[] args) {

       Goods goods = new Goods("特百惠杯子");
       List<Thread> list = new ArrayList<>();

       for(int i=0;i<10;i++){
           Thread thread = new Thread(new Producer(goods),"生产者"+i);
           list.add(thread);
       }

        for(int i=0;i<5;i++){
            Thread thread = new Thread(new Consumer(goods),"消费者"+i);
            list.add(thread);
        }

       for(Thread thread:list){
           //消费者、生产者谁先启动不一定
           thread.start();
       }
    }
}

运行结果部分截图:
java语言实现生产者与消费者模型_第2张图片

2.1.2 多个生产者多个消费者(生产者生产商品数量不固定)

package 生产者消费者模型;

import java.util.ArrayList;
import java.util.List;

//货物类
class Goods {
    private String goods;
    private int count;
    public Goods(String goods) {
        this.goods = goods;
    }

    public int getCount() {
        return count;
    }

    /**
     * 生产者生产货物的方法
     */
    public synchronized void produce(){
        //如果没有库存 商品数量+1
        if(this.count<10){
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.count++;
            System.out.println(Thread.currentThread().getName()+"生产产品"+toString());
        }
        //唤醒所有消费者
        notifyAll();
    }

    /**
     * 消费者消费商品
     */
    public synchronized void consumer(){
        //不断判断执行条件
         /**因为有多个线程 假设消费者线程先执行、由于不止一个消费者
          * 此时可能有多个消费者在等待,如果此时一个生产者生产了商品
          * 消费者线程均被唤醒、如果此时线程2消费产品 此时若用if判断
          * 其余等待线程也会count-- 造成错误 所以需要用while判断
         */
        while(count == 0){
            System.out.println("仓库已空...");
            //消费者等待
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //消费商品 数量-1
        this.count--;
        System.out.println(Thread.currentThread().getName()+"消费产品"+toString());
        //唤醒所有生产者
        notifyAll();
    }

    @Override
    public String toString() {
        return "Goods{" +
                "goods='" + goods + '\'' +
                ", count=" + count +
                '}';
    }
}
//生产者线程
class Producer implements Runnable{
    //生产的货物
    private Goods goods;

    public Producer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        //最大库存为10
        while(true){
            this.goods.produce();
        }
    }
}
//消费者线程
class Consumer implements Runnable{
    //消费的货物
    private Goods goods;

    public Consumer(Goods goods) {
        this.goods = goods;
    }

    @Override
    public void run() {
        while(true){
            this.goods.consumer();
        }
    }
}
public class Test{
    public static void main(String[] args) {

       Goods goods = new Goods("特百惠杯子");
       List<Thread> list = new ArrayList<>();
       
        for(int i=0;i<10;i++){
            Thread thread = new Thread(new Producer(goods),"生产者"+i);
            list.add(thread);
        }
        for(int i=0;i<5;i++){
            Thread thread = new Thread(new Consumer(goods),"消费者"+i);
            list.add(thread);
        }

       for(Thread thread:list){
           //消费者、生产者谁先启动不一定
           thread.start();
       }
    }
}

运行结果部分截图:
java语言实现生产者与消费者模型_第3张图片

你可能感兴趣的:(Java,Java学习)