用阻塞队列LinkedBlockingQueue实现生产者消费者先进先出

更新时间:2023-05-31 05:33:13 阅读: 评论:0

⽤阻塞队列LinkedBlockingQueue实现⽣产者消费者先进先出
LinkedBlockingQueue是⼀个基于已链接节点的、范围任意的blocking queue的实现。 由于LinkedBlockingQueue实现是线程安全的,实现了先进先出等特性,是作为⽣产者消费者的⾸选,LinkedBlockingQueue 可以指定容量,也可以不指定,不指定的话,默认最⼤是Integer.MAX_VALUE,其中主要⽤到put和take⽅法,put⽅法在队列满的时候会阻塞直到有队列成员被消费,take⽅法在队列空的时候会阻塞,直到有队列成员被放进来。
汽车膜品牌此队列按 FIFO(先进先出)排序元素。队列的头部 是在队列中时间最长的元素。队列的尾部 是在队列中时间最短的元素。
新元素插⼊到队列的尾部,并且队列检索操作会获得位于队列头部的元素。链接队列的吞吐量通常要⾼于基于数组的队列,
悬挂系统
但是在⼤多数并发应⽤程序中,其可预知的性能要低。
可选的容量范围构造⽅法参数作为防⽌队列过度扩展的⼀种⽅法。
如果未指定容量,则它等于 Integer.MAX_VALUE。除⾮插⼊节点会使队列超出容量,否则每次插⼊后会动态地创建链接节点。
1:如果未指定容量,默认容量为Integer.MAX_VALUE ,容量范围可以在构造⽅法参数中指定作为防⽌队列过度扩展。
2:此对象是 线程阻塞-安全的
  3:不接受 null 元素
4:它实现了BlockingQueue接⼝。
5:实现了 Collection 和 Iterator 接⼝的所有可选 ⽅法。
6:在JDK5/6中,LinkedBlockingQueue和ArrayBlocingQueue等对象的poll(long timeout, TimeUnit unit)存在内存泄露Leak的对象AbstractQueuedSynchronizer.Node,据称JDK5会在Update12⾥Fix,JDK6会在Update2⾥Fix
绿萝怎么浇水
⽰例代码如下:
[html]
1. package com.st;
2.
3. import urrent.BlockingQueue;
4. import urrent.LinkedBlockingQueue;
5.
6. public class TestBlockingQueue {
7.    static BlockingQueue <Hamburger> queue=new LinkedBlockingQueue<Hamburger>(10);
8.    public static void main(String[] args) throws InterruptedException {
9.        Producer t1 = new Producer();
10.        Consumer t2 = new Consumer();
11.        t1.start();
蛋糕照片
12.        t2.start();
13.        System.out.println("Thread.sleep(1000)");
14.        Thread.sleep(1000);
15.        t2.interrupt();
16.    }
17. }
18. class Hamburger{
19.    int id;
20.    public Hamburger(int id) {
21.        this.id=id;
22.    }
23.
24.    public String toString() {
25.        return "Hamburger: "+id;
26.    }
27. }
28. class Producer extends Thread{
29.
30.    public void run() {
31.        int i=0;
32.        while(i<10){
33.            Hamburger e = new Hamburger(i);
34.            try {
35.                System.out.println("Produce Hamburger: "+i);
36.                TestBlockingQueue.queue.put(e);
37.            } catch (InterruptedException e1) {
38.                System.out.println("Hamburger so many, it was clod.");
39.                return;
40.            }
41.            i++;
42.        }
43.    }
44. }
45. class Consumer extends Thread{
46.
47.    public void run() {
48.        while(true){
49.            try {
50.                System.out.println("Eat Hamburger: "+TestBlockingQueue.queue.take());
51.            } catch (InterruptedException e1) {
52.                System.out.println("Hamburger so less, It was stopped.");
53.                return;
属牛的幸运数字54.            }
55.        }
56.    }
57. }
由于阻塞队列LinkedBlockingQueue,FIFO,使⽤它的put(),take()会判断当前队列是有值,即等待⽣产再消费,即便是两个线程并⾏执⾏,很简单⽅便的解决了⽣产者消费者问题,但是在这⾥需要注意的是在两个run()⽅法中,打印当前⽣产或消费Hamburger的时候,最好把put()和take()⽅法放在相应的打印语句中⼀起执⾏,否则会发⽣先消费后⽣产的后果。 因为打印语句和⽅法的执⾏时两段代码,由于双线程同时执⾏,⽆法保证执⾏的相应代码块的顺序性!!由于最后互相等待会造成死锁,所以在主线程睡眠1秒后打断消费者,让它别等了,抛异常后return结束消费线程,最后整个main⽅法调⽤结束。
ConcurrentLinkedQueue
ConcurrentLinkedQueue是Queue的⼀个安全实现.Queue中元素按FIFO原则进⾏排序.采⽤CAS操作,来保证元素的⼀致性。LinkedBlockingQueue是⼀个线程安全的阻塞队列,它实现了BlockingQueue接⼝,BlockingQueue接⼝继承⾃.util.Queue接⼝,并在这个接⼝的基础上增加了take和put⽅法,这两个⽅法正是队列操作的阻塞版本。
[html]
1. package com.st;
2.
风水住宅3. import urrent.ConcurrentLinkedQueue;
4. import urrent.CountDownLatch;
5. import urrent.ExecutorService;
6. import urrent.Executors;
7.
8. public class ConcurrentLinkedQueueTest {
9.    private static ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<Integer>();
10.    private static int count = 2; // 线程个数
11.    //CountDownLatch,⼀个同步辅助类,在完成⼀组正在其他线程中执⾏的操作之前,它允许⼀个或多个线程⼀直等待。
12.    private static CountDownLatch latch = new CountDownLatch(count);
13.
14.    public static void main(String[] args) throws InterruptedException {
15.        long timeStart = System.currentTimeMillis();
16.        ExecutorService es = wFixedThreadPool(4);
17.        ConcurrentLinkedQueueTest.offer();
18.        for (int i = 0; i < count; i++) {
19.            es.submit(new Poll());
20.        }
21.        latch.await(); //使得主线程(main)阻塞直到untDown()为零才继续执⾏
22.        System.out.println("cost time " + (System.currentTimeMillis() - timeStart) + "ms");
23.        es.shutdown();
24.    }
25.
26.    /**
27.      * ⽣产
28.      */
29.    public static void offer() {
30.        for (int i = 0; i < 100000; i++) {
31.            queue.offer(i);
32.        }
33.    }
34.
35.    /**
36.      * 消费照相记忆
37.      */
38.    static class Poll implements Runnable {
39.        public void run() {
40.            while (queue.size()>0) {
41.            // while (!queue.isEmpty()) {
42.                System.out.println(queue.poll());
43.            }
44.            untDown();
45.        }
46.    }
47. }
运⾏结果:
costtime 1415ms
改⽤while (queue.size()>0)后
承诺函运⾏结果:
cost time 38214ms
结果居然相差那么⼤,看了下ConcurrentLinkedQueue的API原来.size()是要遍历⼀遍集合的,难怪那么慢,所以尽量要避免⽤size⽽改⽤isEmpty().
总结了下, 在缺乏性能测试下,对⾃⼰的编程要求更加要严格,特别是在⽣产环境下更是要⼩⼼谨慎。

本文发布于:2023-05-31 05:33:13,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/818283.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:队列   元素   阻塞   容量
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图