线程基础三

使用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

posted on   luzhouxiaoshuai  阅读(152)  评论(0编辑  收藏  举报

编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示