使用wait()與notifyAll()實現生產者與消費者模式

weixin_42260375發表於2020-10-16

使用wait()與notifyAll()實現生產者與消費者模式

所涉及到的基礎知識

wait()

一、wait是java同步機制中重要的組成部分。結合與synchronized關鍵字使用,否則執行時會收到一個異常:IllegalMonitorStateException。
二、wait屬於Object類。
三、呼叫任意物件的 wait() 方法導致該執行緒阻塞,並且會釋放鎖。

notify()、notifyAll()

一、notify、notifyAll是java同步機制中重要的組成部分。結合與synchronized關鍵字使用。
二、notify、notifyAll屬於Object類。
三、notify與notifyAll沒有太多的區別,只是notify僅喚醒一個執行緒並允許它去獲得鎖,notifyAll是喚醒所有等待這個物件的執行緒並允許它們去獲得物件鎖,只要是在synchronied塊中的程式碼,沒有物件鎖是寸步難行的。其實喚醒一個執行緒就是重新允許這個執行緒去獲得物件鎖並向下執行。

程式碼示例

生產者:

import java.util.List;
import java.util.Random;

public class Productor implements Runnable {
    private final int CAPACITY_SIZE = 5;//容器可容納最大數
    private final List<String> container;
    public Productor(List<String> container){this.container = container;}

    @Override
    public void run() {
        while (true){
            product();
        }
    }
    Random random = new Random();
    private void product(){
        try {
            synchronized (container){
                while (container.size() == CAPACITY_SIZE){
                    System.out.println("容器已經滿了,等待消費者消費");
                    container.wait();
                }
                String productor = getRandomString(5);
                container.add(productor);
                System.out.println("生產出產品:"+productor);
                Thread.sleep(1000);
                container.notifyAll();
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    //length使用者產生字串的長度
    private static String getRandomString(int length){
        String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random=new Random();
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<length;i++){
            int number=random.nextInt(62);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }
}

消費者:



import java.util.List;

public class Consumer implements Runnable {
    private final List<String> container;
    public  Consumer(List<String> container){this.container = container;}
    @Override
    public void run() {
        while (true){
         consum();
        }
    }

    private void consum() {
        try {
            synchronized (container){
                while (container.isEmpty()){
                    System.out.println("已消費完");
                    container.wait();
                }
                System.out.println("消費產品:"+container.get(0));
                container.remove(0);
                Thread.sleep(2000);
                container.notifyAll();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

測試程式碼:

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

public class TestProductorAndConsumer
{
    public static void main(String[] args) {
        List<String> con = new ArrayList<>();
        Productor productor = new Productor(con);
        Consumer consumer = new Consumer(con);
        new Thread(productor).start();
        new Thread(consumer).start();
    }
}

執行結果:
在這裡插入圖片描述

相關文章