线程基础三

使用wait和notify 模拟一个ArrayBlockingQueue 当调用put方法存储元素的时候,如果当前队列已经满了线程阻塞,当使用take获得当前队列的第一个元素的时候,如果队列为null线程阻塞

我们来看看下面的代码:

package com.bjsxt.base.conn009;

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * 模拟Queue
 * @author alienware
 *
 */
public class MyQueue {

    private final LinkedList<Object> list = new LinkedList<Object>();
    
    private final AtomicInteger count = new AtomicInteger(0);
    
    private final int maxSize;
    private final int minSize = 0;
    
    private final Object lock = new Object();
    
    public MyQueue (int maxSize){
        this.maxSize = maxSize;
    }

    public void put (Object obj) {
        synchronized(lock){
            while(count.get() == maxSize){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.add(obj);
            count.getAndIncrement();
            System.out.println(" 元素 " + obj + " 被添加 ");
            lock.notify();
            
        }
    }
    
    public Object take(){
        Object temp = null;
        synchronized (lock) {
            while(count.get() == minSize){
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            count.getAndDecrement();
            temp = list.removeFirst();
            System.out.println(" 元素 " + temp + " 被消费 ");
            lock.notify();
        }
        return temp;
    }
    
    public int size(){
        return count.get();
    }
    
    
    public static void main(String[] args) throws Exception {
        
        final MyQueue m = new MyQueue(5);
        m.put("a");
        m.put("b");
        m.put("c");
        m.put("d");
        m.put("e");
        System.out.println("当前元素个数:" + m.size());
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                m.put("h");
                m.put("i");
            }
        }, "t1");
        
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    Object t1 = m.take();
                    //System.out.println("被取走的元素为:" + t1);
                    Thread.sleep(1000);
                    Object t2 = m.take();
                    //System.out.println("被取走的元素为:" + t2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t2");

        t1.start();
        Thread.sleep(1000);
        t2.start();
        
    }
    
    
    
}

上面代码有几个地方需要注意:

第一因为是多线程操作

所以容器大小的size应该是在多线程下安全   private final AtomicInteger count = new AtomicInteger(0); ,这里使用AtomicInteger 类来保证线程的安全

第二,在判断的时候

   while(count.get() == minSize)
使用的是while不是if,这也是编程需要注意的
只有和wait和notify配合使用的,官方推荐使用while,而不使用if
原文地址:https://www.cnblogs.com/kebibuluan/p/7612277.html