使用wait()和notify()模拟Queue(队列)

来源:互联网 发布:什么是网络电视机 编辑:程序博客网 时间:2024/04/30 17:48

在java多线程中,JDK为我们提供了wait和notify实现对进程的控制,两者要和synchronized关键字一起使用,并且需要先获取对象锁。wait是释放锁,notify是不释放锁。

举个例子:

ListDemo代码:

public class ListDemo{        private static LinkedList<Integer> list = new LinkedList<>();        public static void add(){        list.add(1);    }        public static int size(){        return list.size();    }}
线程A:

public class ThreadA implements Runnable {    private Object obj;    ThreadA(){    }    public ThreadA(Object obj){        this.obj = obj;    }    @Override    public void run() {        try{            synchronized (obj){                if(MyList.size()!=5){                    System.out.println("wait begin"+System.currentTimeMillis());                    obj.wait();                    System.out.println("wait end"+System.currentTimeMillis());                }            }        }catch (InterruptedException e){            e.printStackTrace();        }    }}
线程B:

public class ThreadB implements Runnable{    private Object obj;    ThreadB(){    }    public ThreadB(Object obj){        super();        this.obj = obj;    }    @Override    public void run() {        try{            synchronized (obj){                for(int i=0;i<10;i++){                    MyList.add();                    if(MyList.size()==5){                        obj.notify();                        System.out.println("已经发出通知");                    }                    System.out.println("添加了"+i+"个元素");                    Thread.sleep(1000);                }            }        }catch (InterruptedException e){            e.printStackTrace();        }    }}
主方法:

public class Main {    public static void main(String[] args){        try{            Object obj = new Object();            new Thread(new ThreadA(obj)).start();            Thread.sleep(1000);            new Thread(new ThreadB(obj)).start();        }catch (InterruptedException e){            e.printStackTrace();        }    }}
运行结果:


线程A一直等到线程B执行结束后才继续执行,可见wait释放锁,而notify不释放锁。

使用wait和notify模拟队列:

使用wait和notify实现阻塞的放入和取出(先进先出),思路:初始为队列的最大长度为5;添加一个元素时,判断队列大小是否为5,若是则等待添加;移除一个元素是,判断队列大小是否为0,若是则等待移除。实现代码如下:

public class MyQueue {    //用一个线程安全的List实现数据存放    private final LinkedList<Object> list = new LinkedList<>();    private final AtomicInteger count = new AtomicInteger(); //计数器    private final int maxSize = 5;    private final int minSize = 0;    //初始化锁对象    private final Object lock = new Object();    /**     * put方法     */    public void put(Object obj){        synchronized (lock){            while (count.get() == maxSize){                try{                    lock.wait();                }catch (InterruptedException e){                    e.printStackTrace();                }            }            list.add(obj);            //在AtomicInteger中getAndIncrement以原子方式将当前值加1。            count.getAndIncrement();            System.out.println("元素"+obj+"被添加");            lock.notify();        }    }    /**     * get方法     */    public Object get(){        Object temp;        synchronized (lock){            while (count.get()==minSize){                try {                    lock.wait();                }catch (InterruptedException e){                    e.printStackTrace();                }            }            count.getAndDecrement();            //获取List的第一个元素并且返回            temp = list.removeFirst();            System.out.println("元素"+temp+"被移除");            lock.notify();        }        return  temp;    }    public static void main(String[] args) throws InterruptedException{        final MyQueue myQueue = new MyQueue();        initQueue(myQueue);        Thread th1 = new Thread(new Runnable() {            @Override            public void run() {                myQueue.put("f");                myQueue.put("g");            }        });        Thread th2 = new Thread(new Runnable() {            @Override            public void run() {                try{                    Thread.sleep(1000);                    myQueue.get();                    Thread.sleep(1000);                    myQueue.get();                }catch (InterruptedException e){                    e.printStackTrace();                }            }        });        th1.start();        Thread.sleep(1000);        th2.start();    }    private int size(){        return count.get();    }    private static void initQueue(MyQueue myQueue){        myQueue.put("a");        myQueue.put("b");        myQueue.put("c");        myQueue.put("d");        myQueue.put("e");        System.out.println("当前个数"+myQueue.size());    }}
运行结果: