LinkedBlockingQueue

探讨LinkedBlockingQueue方法差异及用法
本文详细解析了LinkedBlockingQueue中的add、put、offer三种添加元素的方法,以及从队列中取出并移除头元素的poll、remove、take方法。通过实例演示了它们在操作队列时的不同表现,帮助理解队列管理和线程同步的基本概念。

ava.util.concurrent包下的新类。LinkedBlockingQueue就是其中之一,顾名思义这是一个阻塞的线程安全的队列,底层应该采用链表实现。

       看其API的时候发现,添加元素的方法竟然有三个:add,put,offer。

且这三个元素都是向队列尾部添加元素的意思。于是我产生了兴趣,要仔细探究一下他们之间的差别。

1.首先看一下add方法:

    Inserts the specified element into this queue if it is possible to do so immediately without violating capacity restrictions, returning true upon success and throwing an IllegalStateException if no space is currently available. 

    This implementation returns true if offer succeeds, else throws an IllegalStateException.

        LinkedBlockingQueue构造的时候若没有指定大小,则默认大小为Integer.MAX_VALUE,当然也可以在构造函数的参数中指定大小。LinkedBlockingQueue不接受null。

       add方法在添加元素的时候,若超出了度列的长度会直接抛出异常:

public static void main(String args[]){
		try {
			LinkedBlockingQueue<String> queue=new LinkedBlockingQueue(2);
			
			queue.add("hello");
			queue.add("world");
			queue.add("yes");
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
//运行结果:
java.lang.IllegalStateException: Queue full
	at java.util.AbstractQueue.add(Unknown Source)
	at com.wjy.test.GrandPather.main(GrandPather.java:12)

 

2.再来看一下put方法:

    Inserts the specified element at the tail of this queue, waiting if necessary for space to become available.

      对于put方法,若向队尾添加元素的时候发现队列已经满了会发生阻塞一直等待空间,以加入元素。

public static void main(String args[]){
		try {
			LinkedBlockingQueue<String> queue=new LinkedBlockingQueue(2);
			
			queue.put("hello");
			queue.put("world");
			queue.put("yes");
			
			System.out.println("yes");
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
//运行结果:
//在queue.put("yes")处发生阻塞
//下面的“yes”无法输出

 

3.最后看一下offer方法:

     Inserts the specified element at the tail of this queue if it is possible to do so immediately without exceeding the queue's capacity, returning true upon success and false if this queue is full. When using a capacity-restricted queue, this method is generally preferable to method add, which can fail to insert an element only by throwing an exception.

   

    offer方法在添加元素时,如果发现队列已满无法添加的话,会直接返回false。

 

public static void main(String args[]){
		try {
			LinkedBlockingQueue<String> queue=new LinkedBlockingQueue(2);
			
			boolean bol1=queue.offer("hello");
			boolean bol2=queue.offer("world");
			boolean bol3=queue.offer("yes");
			
			System.out.println(queue.toString());
			System.out.println(bol1);
			System.out.println(bol2);
			System.out.println(bol3);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
//运行结果:
[hello, world]
true
true
false

 

    好了,竟然说了这么多了,就把从队列中取元素的方法也顺便一说。

从队列中取出并移除头元素的方法有:poll,remove,take。

 

poll: 若队列为空,返回null。

remove:若队列为空,抛出NoSuchElementException异常。

take:若队列为空,发生阻塞,等待有元素。

### Java `LinkedBlockingQueue` 使用方法 #### 创建 `LinkedBlockingQueue` 可以通过无参构造函数创建一个具有默认容量(`Integer.MAX_VALUE`)的队列,也可以通过指定容量的方式创建: ```java // 默认容量为 Integer.MAX_VALUE 的 LinkedBlockingQueue LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(); // 容量为 10 的 LinkedBlockingQueue LinkedBlockingQueue<Integer> boundedQueue = new LinkedBlockingQueue<>(10); ``` [^2] #### 基本操作 - **插入元素** 向队列中添加元素的方法有多种选择。对于不会抛出异常的操作,当尝试往已满的队列中加入新项时会返回特定的结果;而对于可能会抛出异常的情况,则会在违反约束条件时立即报错。 ```java boolean offerResult = queue.offer("item"); // 如果成功则返回 true, 否则 false (不等待) try { boolean timedOfferResult = queue.offer("another item", 5L, TimeUnit.SECONDS); // 尝试最多五秒的时间去放置项目 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } ``` [^1] - **移除元素** 从队列头部取出并删除元素也有几种不同的方式可以选择,具体取决于是否希望在遇到空队列的情况下得到提示还是愿意无限期地等待直至可用为止。 ```java String pollItem = queue.poll(); // 获取头元素并移除此元素; 若为空则返回 null 或者超时期间未找到任何东西就返回null try { String takeItem = queue.take(); // 取得下一个待处理的任务,如果没有任务存在就会一直阻塞当前线程直到有新的条目到来 } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } // 移除所有元素 queue.clear(); ``` - **查询队列状态** 有时需要检查队列的状态而不做修改动作,比如查看是否有剩余空间或者确认某个对象是否存在其中。 ```java int size = queue.size(); // 返回队列中的元素数目 boolean containsElement = queue.contains("test element"); ``` [^4] #### 生产者-消费者模式示例 下面是一个简单的例子展示了如何利用 `LinkedBlockingQueue` 实现经典的生产者-消费者问题解决方案: ```java class Producer implements Runnable { private final BlockingQueue<String> queue; public Producer(BlockingQueue<String> q) { this.queue = q; } @Override public void run() { try { while(true){ String product = "product-" + System.currentTimeMillis(); queue.put(product); System.out.println(Thread.currentThread().getName()+" produced "+product); Thread.sleep((long)(Math.random()*100)); } }catch(Exception ex){ /* handle exception */ } } } class Consumer implements Runnable { private final BlockingQueue<String> queue; public Consumer(BlockingQueue<String> q) {this.queue=q;} @Override public void run(){ try{ while(true){ String consumedProduct=queue.take(); System.out.println(Thread.currentThread().getName()+" consumed "+consumedProduct); Thread.sleep((long)(Math.random()*100)); } }catch(Exception ex){/*handle exception*/} } } public class Main { public static void main(String[] args)throws Exception{ int capacity = 10; LinkedBlockingQueue<String> sharedQueue=new LinkedBlockingQueue<>(capacity); ExecutorService executor=Executors.newCachedThreadPool(); for(int i=0;i<3;++i)//启动三个生产者线程 executor.execute(new Producer(sharedQueue)); for(int j=0;j<2;++j)//启动两个消费者线程 executor.execute(new Consumer(sharedQueue)); Thread.sleep(5000);//让程序运行一段时间后结束 executor.shutdownNow();//关闭执行服务 } } ``` [^5]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值