wait()與notify() 實現簡單的生產與消費

wait、notify、notifyAll 的用法java

簡單的生產者與消費者

實現思路: 消費與生產都須要獲取隊列的控制權,獲取後都須要斷定隊列的運行容量狀態,只有當知足條件時才能向下執行,並在跳出同步塊時真正釋放控制權。測試

import java.util.LinkedList;
import java.util.Queue;



public class Storage {

    private int           capacity = 10;
    private Queue<Object> queue    = new LinkedList<Object>();

    public void produce(int num) {
        synchronized (queue) {
            while (queue.size() + num > capacity) {
                System.out.println("【要生產的產品數量】:" + num + "\t【庫存量】:" + queue.size() + "\t暫時不能執行生產任務!");
                try {
                    queue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            queue.notifyAll(); // 此時並不會釋放控制權。 只有跳出synchronized塊才釋放

            for (int i = 0; i < num; i++) {
                queue.add(new Object());
            }
            System.out.println("【已經生產產品數】:" + num + "\t【現倉儲量爲】:" + queue.size());

        }

    }

    public void consume(int num) {
        synchronized (queue) {
            while (num > queue.size()) {
                System.out.println("【要消費的產品數量】:" + num + "\t【庫存量】:" + queue.size() + "\t暫時不能執行消費任務!");
                try {
                    queue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            for (int i = 0; i < num; i++) {
                queue.remove();
            }
            System.out.println("【已經消費產品數】:" + num + "\t【現倉儲量爲】:" + queue.size());
            queue.notifyAll();
        }

    }

    public static void main(String[] args) {
        Storage storage = new Storage();
        for (int i = 0; i < 5; i++) {
            final int num = i;
            new Thread(() -> {
                while (true) {
                    storage.produce(num);
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        for (int i = 0; i < 2; i++) {
            final int num = i;
            new Thread(() -> {
                while (true) {
                    storage.consume(num);
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

測試結果:spa

交替輸出

eg.1 : 沒有內部的斷定條件,則只能靠wait()方法的這方控制.net

public class SyncTest {

    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();

        new Thread(() -> {
            while (true) {
                synchronized (obj) {
                    try {
                        obj.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    System.out.println("1"); // 在wait()前或後都行,只是影響第一次輸出的是1或2
                }
            }
        }).start();

        Thread.sleep(100);

        new Thread(() -> {
            while (true) {
                synchronized (obj) {
                    System.out.println("2");
                    obj.notifyAll();
                }
                try {
                    Thread.sleep(1);//不限制的話,一直輸出的是2
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }   ).start();
    }

}

eg.2 : 若是有內部斷定條件,則兩邊都能有控制code

import java.util.LinkedList;
import java.util.Queue;

public class SyncTest {

    public static void main(String[] args) throws InterruptedException {
        Queue<Object> obj = new LinkedList<Object>();

        new Thread(() -> {
            while (true) {
                synchronized (obj) {
                    if (obj.size() == 1) {
                        System.out.println("1");
                        try {
                            obj.wait();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    } else {
                        obj.add(new Object());
                        obj.notify();
                    }
                }
            }
        }).start();

        new Thread(() -> {
            while (true) {
                synchronized (obj) {
                    if (obj.size() != 1) {
                        System.out.println("2");
                        try {
                            obj.wait();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    } else {
                        obj.remove();
                        obj.notify();
                    }
                }
            }
        }).start();
    }

}

測試結果:blog

相關文章
相關標籤/搜索