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两种操作方式,即可以从队列的头和尾同时操作(插入/删除),用法差别也不大,不作介绍。

posted @ 2019-01-21 20:55  橘子洲头。  阅读(497)  评论(0编辑  收藏  举报