• Java多线程_JUC包下的阻塞队列


    在前面我们提到了阻塞队列,也用过了LinkedBolckingQueue队列了,在这里,我们主要对 ArrayBlockingQueue,PriorityBlockingQueue,DelayQueue,SynchronousQueue,LinkedTransferQueue,LinkedBlockingDeque的使用方法和应用场景做一个补充。

    • ArrayBlockingQueue:基于数组实现的阻塞队列,先进先出队列,有界队列。在创建时必须制定容量大小。并可以指定公平性与非公平性,默认情况下是非公平的,即不保证等待时间最长的队列最优先能够访问队列。
    • LinkedBlockingQueue:基于链表实现的阻塞队列,先进先出队列,有界队列。在创建时如果不指定容量大小,则默认大小为Integer.MAX_VALUE。
    • PriorityBlockingQueue:按照元素的优先级对元素进行排序,按照优先级顺序出队。并且该阻塞队列为无界阻塞队列,即容量没有上限(源码中它没有容器满的信号标志)。
    • DelayQueue:基于PriorityQueue的延时阻塞队列,无界队列。DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。因为DelayQueue是一个无界队列,所以往队列中插入数据的操作永远不会被阻塞,而只有获取数据的操作才会被阻塞。
    • SynchronousQueue:一个不存储元素的阻塞队列。
    • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
    • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

    (1) ArrayBlockingQueue示例:

    import java.util.concurrent.ArrayBlockingQueue;
    
    public class ArrayBolckingQueueDemo {
    	static ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(2);
    
    	public static void main(String[] args) {
    		ArrayBolckingQueueDemo demo = new ArrayBolckingQueueDemo();
    		Product p = demo.new Product();
    		Eat e = demo.new Eat();
    		Thread t1 = new Thread(e);
    		Thread t2 = new Thread(p);
    		t2.start();
    		t1.start();
    	}
    
    	class Product implements Runnable {
    
    		@Override
    		public void run() {
    			while (true) {
    				try {
    					queue.put("apple");
    					System.out.println(Thread.currentThread().getName() + "put  queue:" + queue.toString());
    					Thread.sleep(1000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    
    			}
    
    		}
    	}
    
    	class Eat implements Runnable {
    
    		@Override
    		public void run() {
    			while (true) {
    				try {
    					queue.take();
    					System.out.println(Thread.currentThread().getName() + "eat queue:" + queue.toString());
    					Thread.sleep(1500);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			}
    
    		}
    	}
    }

      结果:

    (2)LinkedBlockingQueue示例这里不介绍,大家可以看我前面的博客“Java多线程_阻塞队列”
    (3)PriorityBlockingQueue示例:

    import java.util.concurrent.PriorityBlockingQueue;
    
    public class PriorityBlockingQueueDemo {
        public static void main(String[] args) {
            PriorityBlockingQueue<People> queue = new PriorityBlockingQueue<>();
            PriorityBlockingQueueDemo demo = new PriorityBlockingQueueDemo();
            queue.put(demo.new People("tom", 19));
            queue.put(demo.new People("jack", 18));
            queue.put(demo.new People("tony", 21));
            while (!queue.isEmpty()) {
                try {
                    System.out.println(queue.take().toString());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        class People implements Comparable<People> {
            private String name;
            private Integer age;
    
            public People(String name, Integer age) {
                super();
                this.name = name;
                this.age = age;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            public Integer getAge() {
                return age;
            }
    
            public void setAge(Integer age) {
                this.age = age;
            }
    
            @Override
            public int compareTo(People o) {
                if (this.age > o.age) {
                    return 1;
                } else {
                    return -1;
                }
            }
    
            @Override
            public String toString() {
                // TODO Auto-generated method stub
                return "name:" + name + " age:" + age;
            }
    
        }
    }

    结果:

    (4)DelayQueue应用场景:
    1) 关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭。
    2) 缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出。
    3) 任务超时处理。

    import java.util.concurrent.DelayQueue;
    import java.util.concurrent.Delayed;
    import java.util.concurrent.TimeUnit;
    
    public class DelayQueueDemo {
        public static void main(String[] args) {
            DelayQueueDemo demo = new DelayQueueDemo();
            DelayQueue<People> queue = new DelayQueue<>();
            queue.put(demo.new People("tom", 4000 + System.currentTimeMillis()));
            queue.put(demo.new People("jack", 1000 + System.currentTimeMillis()));
            queue.put(demo.new People("tony", 6000 + System.currentTimeMillis()));
            while (!queue.isEmpty()) {
                try {
                    System.out.println(queue.take().toString());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
        class People implements Delayed {
            private String name;
            private long time;// 截止时间
    
            public People(String name, long time) {
                super();
                this.name = name;
                this.time = time;
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            public long getTime() {
                return time;
            }
    
            public void setTime(long time) {
                this.time = time;
            }
    
            @Override
            public String toString() {
                return "name:" + name + "  time:" + time;
            }
    
            @Override
            public int compareTo(Delayed o) {
                People p = (People) o;
                if (time - p.time > 0) {
                    return 1;
                } else {
                    return -1;
                }
            }
    
            @Override
            public long getDelay(TimeUnit unit) {
                return time - System.currentTimeMillis();
            }
        }
    }

    结果:

    (5)SynchronousQueue示例:
    注意点:每个 put 必须等待一个 take,反之亦然。

    import java.util.Random;
    import java.util.concurrent.SynchronousQueue;
    
    public class SynchronousQueueDemo {
        static SynchronousQueue<Integer> queue = new SynchronousQueue<>();
    
        public static void main(String[] args) {
            SynchronousQueueDemo demo = new SynchronousQueueDemo();
            Productor p = demo.new Productor();
            Consumer c = demo.new Consumer();
            Thread t1 = new Thread(p);
            Thread t2 = new Thread(c);
            t1.start();
            t2.start();
        }
    
        class Productor implements Runnable {
    
            @Override
            public void run() {
                while (true) {
                    int data = new Random().nextInt(1000);
                    System.out.println("put " + data);
                    try {
                        queue.put(data);
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    
        class Consumer implements Runnable {
    
            @Override
            public void run() {
                while (true) {
                    try {
                        System.out.println("take " + queue.take());
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    }

    结果:

    (6)LinkedBlockingDeque和LinkedTransferQueue
    这两个队列都是后期才产生的队列。
    LinkedTransferQueue是一个由链表结构组成的无界阻塞队列。他与LinkedBolckingQueue最大的不同就是这个队列是无界的,而LinkedBolckingQueue是有界的,用法大致相同,这里不作介绍。
    LinkedBlockingDeque最大的不同就是它是一个双向的基于链表的阻塞队列。该阻塞队列同时支持FIFO和FILO两种操作方式,即可以从队列的头和尾同时操作(插入/删除),用法差别也不大,不作介绍。

  • 相关阅读:
    求阶乘及其和
    JAVA 字符串题目 以静态方法实现encode()和decode()的调用
    JAVA 类与对象题目5
    JAVA 类与对象题目4
    JAVA 类与对象题目3
    JAVA 类与对象题目2
    JAVA 基础练习题代码
    JAVA 关于值类型和引用类型的区别
    JAVA学习 判断一个字符或字符是否位于另一个字符串的末尾
    JAVA 截取4个随机数字字母的代码
  • 原文地址:https://www.cnblogs.com/ericz2j/p/10300953.html
Copyright © 2020-2023  润新知