JAVA阻塞队列LinkedBlockingQueue 以及非阻塞队列ConcurrentLinkedQueue 的区别

阻塞队列:线程安全

按 FIFO(先进先出)排序元素。队列的头部 是在队列中时间最长的元素。队列的尾部 是在队列中时间最短的元素。新元素插入到队列的尾部,并且队列检索操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。

注意:

1、必须要使用take()方法在获取的时候达成阻塞结果
2、使用poll()方法将产生非阻塞效果

 
    
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class BlockingDeque {
//阻塞队列,FIFO
private static LinkedBlockingQueue<Integer> concurrentLinkedQueue = new LinkedBlockingQueue<Integer>();

public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(2);

 executorService.submit(</span><span style="color:#0000ff;">new</span> Producer(<span style="color:#800000;">"</span><span style="color:#800000;">producer1</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
 executorService.submit(</span><span style="color:#0000ff;">new</span> Producer(<span style="color:#800000;">"</span><span style="color:#800000;">producer2</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
 executorService.submit(</span><span style="color:#0000ff;">new</span> Producer(<span style="color:#800000;">"</span><span style="color:#800000;">producer3</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
 executorService.submit(</span><span style="color:#0000ff;">new</span> Consumer(<span style="color:#800000;">"</span><span style="color:#800000;">consumer1</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
 executorService.submit(</span><span style="color:#0000ff;">new</span> Consumer(<span style="color:#800000;">"</span><span style="color:#800000;">consumer2</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
 executorService.submit(</span><span style="color:#0000ff;">new</span> Consumer(<span style="color:#800000;">"</span><span style="color:#800000;">consumer3</span><span style="color:#800000;">"</span><span style="color:#000000;">));  

}

static class Producer implements Runnable {
private String name;

 </span><span style="color:#0000ff;">public</span><span style="color:#000000;"> Producer(String name) {  
     </span><span style="color:#0000ff;">this</span>.name =<span style="color:#000000;"> name;  
 }  

 </span><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span><span style="color:#000000;"> run() {  
     </span><span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i = <span style="color:#800080;">1</span>; i &lt; <span style="color:#800080;">10</span>; ++<span style="color:#000000;">i) {  
         System.</span><span style="color:#0000ff;">out</span>.println(name+ <span style="color:#800000;">"</span><span style="color:#800000;">  生产: </span><span style="color:#800000;">"</span> +<span style="color:#000000;"> i);  
         </span><span style="color:#008000;">//</span><span style="color:#008000;">concurrentLinkedQueue.add(i);  </span>
         <span style="color:#0000ff;">try</span><span style="color:#000000;"> {
            concurrentLinkedQueue.put(i);
            Thread.sleep(</span><span style="color:#800080;">200</span>); <span style="color:#008000;">//</span><span style="color:#008000;">模拟慢速的生产,产生阻塞的效果</span>
        } <span style="color:#0000ff;">catch</span><span style="color:#000000;"> (InterruptedException e1) {
            </span><span style="color:#008000;">//</span><span style="color:#008000;"> TODO Auto-generated catch block</span>

e1.printStackTrace();
}

     }  
 }  

}

static class Consumer implements Runnable {
private String name;

 </span><span style="color:#0000ff;">public</span><span style="color:#000000;"> Consumer(String name) {  
     </span><span style="color:#0000ff;">this</span>.name =<span style="color:#000000;"> name;  
 }  
 </span><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span><span style="color:#000000;"> run() {  
     </span><span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i = <span style="color:#800080;">1</span>; i &lt; <span style="color:#800080;">10</span>; ++<span style="color:#000000;">i) {  
         </span><span style="color:#0000ff;">try</span><span style="color:#000000;"> {          
                </span><span style="color:#008000;">//</span><span style="color:#008000;">必须要使用take()方法在获取的时候阻塞</span>
                  System.<span style="color:#0000ff;">out</span>.println(name+<span style="color:#800000;">"</span><span style="color:#800000;">消费: </span><span style="color:#800000;">"</span> +<span style="color:#000000;">  concurrentLinkedQueue.take());  
                  </span><span style="color:#008000;">//</span><span style="color:#008000;">使用poll()方法 将产生非阻塞效果
                  </span><span style="color:#008000;">//</span><span style="color:#008000;">System.out.println(name+"消费: " +  concurrentLinkedQueue.poll());  
                 
                 </span><span style="color:#008000;">//</span><span style="color:#008000;">还有一个超时的用法,队列空时,指定阻塞时间后返回,不会一直阻塞
                 </span><span style="color:#008000;">//</span><span style="color:#008000;">但有一个疑问,既然可以不阻塞,为啥还叫阻塞队列?
                </span><span style="color:#008000;">//</span><span style="color:#008000;">System.out.println(name+" Consumer " +  concurrentLinkedQueue.poll(300, TimeUnit.MILLISECONDS));                    </span>
            } <span style="color:#0000ff;">catch</span><span style="color:#000000;"> (Exception e) {
                </span><span style="color:#008000;">//</span><span style="color:#008000;"> TODO Auto-generated catch block</span>

e.printStackTrace();
}

     }  
 }  

}
}

 

 

 

 

非阻塞队列

基于链接节点的、无界的、线程安全。此队列按照 FIFO(先进先出)原则对元素进行排序。队列的头部 是队列中时间最长的元素。队列的尾部 是队列中时间最短的元素。新的元素插入到队列的尾部,队列检索操作从队列头部获得元素。当许多线程共享访问一个公共 collection 时,ConcurrentLinkedQueue 是一个恰当的选择。此队列不允许 null 元素。

 

例子

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;

public class NoBlockQueue {
private static ConcurrentLinkedQueue<Integer> concurrentLinkedQueue = new ConcurrentLinkedQueue<Integer>();

</span><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">void</span><span style="color:#000000;"> main(String[] args) {  
    ExecutorService executorService </span>= Executors.newFixedThreadPool(<span style="color:#800080;">2</span><span style="color:#000000;">);  

    executorService.submit(</span><span style="color:#0000ff;">new</span> Producer(<span style="color:#800000;">"</span><span style="color:#800000;">producer1</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
    executorService.submit(</span><span style="color:#0000ff;">new</span> Producer(<span style="color:#800000;">"</span><span style="color:#800000;">producer2</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
    executorService.submit(</span><span style="color:#0000ff;">new</span> Producer(<span style="color:#800000;">"</span><span style="color:#800000;">producer3</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
    executorService.submit(</span><span style="color:#0000ff;">new</span> Consumer(<span style="color:#800000;">"</span><span style="color:#800000;">consumer1</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
    executorService.submit(</span><span style="color:#0000ff;">new</span> Consumer(<span style="color:#800000;">"</span><span style="color:#800000;">consumer2</span><span style="color:#800000;">"</span><span style="color:#000000;">));  
    executorService.submit(</span><span style="color:#0000ff;">new</span> Consumer(<span style="color:#800000;">"</span><span style="color:#800000;">consumer3</span><span style="color:#800000;">"</span><span style="color:#000000;">));  

}  

</span><span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span><span style="color:#000000;"> Producer implements Runnable {  
    </span><span style="color:#0000ff;">private</span><span style="color:#000000;"> String name;  

    </span><span style="color:#0000ff;">public</span><span style="color:#000000;"> Producer(String name) {  
        </span><span style="color:#0000ff;">this</span>.name =<span style="color:#000000;"> name;  
    }  

    </span><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span><span style="color:#000000;"> run() {  
        </span><span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i = <span style="color:#800080;">1</span>; i &lt; <span style="color:#800080;">10</span>; ++<span style="color:#000000;">i) {  
            System.</span><span style="color:#0000ff;">out</span>.println(name+ <span style="color:#800000;">"</span><span style="color:#800000;"> start producer </span><span style="color:#800000;">"</span> +<span style="color:#000000;"> i);  
            concurrentLinkedQueue.add(i);  
            </span><span style="color:#0000ff;">try</span><span style="color:#000000;"> {
                Thread.sleep(</span><span style="color:#800080;">20</span><span style="color:#000000;">);
            } </span><span style="color:#0000ff;">catch</span><span style="color:#000000;"> (InterruptedException e) {
                </span><span style="color:#008000;">//</span><span style="color:#008000;"> TODO Auto-generated catch block</span>

e.printStackTrace();
}
//System.out.println(name+"end producer " + i);
}
}
}

</span><span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span><span style="color:#000000;"> Consumer implements Runnable {  
    </span><span style="color:#0000ff;">private</span><span style="color:#000000;"> String name;  

    </span><span style="color:#0000ff;">public</span><span style="color:#000000;"> Consumer(String name) {  
        </span><span style="color:#0000ff;">this</span>.name =<span style="color:#000000;"> name;  
    }  
    </span><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span><span style="color:#000000;"> run() {  
        </span><span style="color:#0000ff;">for</span> (<span style="color:#0000ff;">int</span> i = <span style="color:#800080;">1</span>; i &lt; <span style="color:#800080;">10</span>; ++<span style="color:#000000;">i) {  
            </span><span style="color:#0000ff;">try</span><span style="color:#000000;"> {

                System.</span><span style="color:#0000ff;">out</span>.println(name+<span style="color:#800000;">"</span><span style="color:#800000;"> Consumer </span><span style="color:#800000;">"</span> +<span style="color:#000000;">  concurrentLinkedQueue.poll());

            } </span><span style="color:#0000ff;">catch</span><span style="color:#000000;"> (Exception e) {
                </span><span style="color:#008000;">//</span><span style="color:#008000;"> TODO Auto-generated catch block</span>

e.printStackTrace();
}
// System.out.println();
// System.out.println(name+" end Consumer " + i);
}
}
}
}

 

在并发编程中,一般推荐使用阻塞队列,这样实现可以尽量地避免程序出现意外的错误。阻塞队列使用最经典的场景就是socket客户端数据的读取和解析,读取数据的线程不断将数据放入队列,然后解析线程不断从队列取数据解析。还有其他类似的场景,只要符合生产者-消费者模型的都可以使用阻塞队列。

 

使用非阻塞队列,虽然能即时返回结果(消费结果),但必须自行编码解决返回为空的情况处理(以及消费重试等问题)。

另外他们都是线程安全的,不用考虑线程同步问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值