1.非阻塞
1.1,PriorityQueue:优先级队列,存入的元素可以实现Comparable,从而按照自定义的顺序去执行
1.2,LinkedList:双向链表,实现了Dequeue接口
2.阻塞
2.1,ArrayBlockingQueue:数组队列
a.底层是数组,读取快,增删慢
b.指定公平性(是否让等待最长的队列先执行),默认不公平
public ArrayBlockingQueue(int capacity, boolean fair),fair:公平
c.创建时必须指定大小
d.先进先出(公平性是另一个范畴,公平性是相对于队列的消费者而言的)
2.2,LinkedBlockingQueue:链表队列
a.底层是双向链表,增删快,读取慢
b.可以不指定容量大小,默认Integer.MAX_VALUE
c.没有公平性一说
d.先进先出(公平性是另一个范畴,公平性是相对于队列的消费者而言的)
2.3,PriorityBlockingQueue:优先级队列
a.需要传入一个Comparable的实现类,即自定义优先级
b.此队列是无界队列,但是可以指定初始容量,大最大容量没有限制,插入元素不 会被阻塞
2.4,DelayQueue:延时队列
a.无界队列,插入元素不会被阻塞
b.只有当指定的延时时间到了才能从队列中获得元素
3.方法
3.1.阻塞队列和非阻塞队列的通用方法
3.1.1增
add(E e):将元素e插入到队列末尾,如果插入成功,则返回true;如果插入失败(即 队列已满),则会抛出异常;
offer(E e):将元素e插入到队列末尾,如果插入成功,则返回true;如果插入失败(即队列已满),则返回false;
3.1.2删
remove():移除队首元素,若移除成功,则返回true;如果移除失败(队列为空),则会抛出异常;
poll():移除并获取队首元素,若成功,则返回队首元素;否则返回null;
3.1.3查
poll():移除并获取队首元素,若成功,则返回队首元素;否则返回null;
peek():获取队首元素,若成功,则返回队首元素;否则返回null
一般用:offer(E e),poll(),peek()
2.阻塞队列的特有方法
3.2.1增
put(E e)方法用来向队尾存入元素,如果队列满,则等待
offer(E e,long timeout, TimeUnit unit)方法用来向队尾存入元素,如果队列满,则等待一定的时间,当时间期限达到时,如果还没有插入成功,则返回false;否则返回true;
3.2.2查
take方法用来从队首取元素,如果队列为空,则等待;
poll(long timeout, TimeUnit unit)方法用来从队首取元素,如果队列空,则等待一定的时间,当时间期限达到时,如果取到,则返回null;否则返回取得的元素;
4.代码示例
阻塞队列不用自己写线程等待和唤醒的代码,很方便
1.下面先使用Object.wait()和Object.notify()、非阻塞队列实现生产者-消费者模式:
class Test {
private int queueSize = 10;
private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
public static void main(String[] args) {
Test test = new Test();
Consumer consumer = test.new Consumer();
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
Producer producer = test.new Producer();
producer.start();
consumer.start();
}
class Consumer extends Thread{
@Override
public void run() {
consume();
}
private void consume() {
while(true){
synchronized (queue) {
while(queue.size() == 0){
try {
System.out.println("队列空,等待数据");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
queue.notify();
}
}
queue.poll(); //每次移走队首元素
queue.notify();
System.out.println("从队列取走一个元素,队列剩余"+queue.size()+"个元素");
}
}
}
}
class Producer extends Thread{
@Override
public void run() {
produce();
}
private void produce() {
while(true){
synchronized (queue) {
while(queue.size() == queueSize){
try {
System.out.println("队列满,等待有空余空间");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
queue.notify();
}
}
queue.offer(1); //每次插入一个元素
queue.notify();
System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
}
}
}
}
}
2.下面是使用阻塞队列实现的生产者-消费者模式:
class Test {
private int queueSize = 10;
private ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(queueSize);
public static void main(String[] args) {
Test test = new Test();
Producer producer = test.new Producer();
Consumer consumer = test.new Consumer();
producer.start();
consumer.start();
}
class Consumer extends Thread{
@Override
public void run() {
consume();
}
private void consume() {
while(true){
try {
queue.take();
System.out.println("从队列取走一个元素,队列剩余"+queue.size()+"个元素");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Producer extends Thread{
@Override
public void run() {
produce();
}
private void produce() {
while(true){
try {
queue.put(1);
System.out.println("向队列取中插入一个元素,队列剩余空间:"+(queueSize-queue.size()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}