多线程-并发包-队列
有界、无界;阻塞队列、非阻塞队列
ConcurrentLinkedDeque
是一个适合用于高并发场景下的队列,通过无锁的方式,实现了高并发状态下的高性能,通常 ConcurrentLinkedQueue 性能好于 BlockingQueue。它是一个基于链接节点的 无界线程安全队列。该队列的元素遵循先进先出的原则。头是最先加入的,尾是最近加入的,该队列不允许 null 元素。
add 和 offer 都是加入元素的方法(在 ConcurrentLinkedQueue 中这两个方法没有任何区别)
poll 和 peek 都是取头元素节点,区别在于前者会删除元素,后者不会。
代码示例:
package com.test.thread.concurrent.queue;
import java.util.concurrent.ConcurrentLinkedDeque;
/**
* 无界限队列
* Created by husz1 on 2019/4/17.
*/
public class ConcurrentLinkedDequeDemo {
public static void main(String[] args) {
ConcurrentLinkedDeque linkedDeque = new ConcurrentLinkedDeque();
linkedDeque.offer("张三");
linkedDeque.offer("李四");
System.out.println(linkedDeque.size());
// 取出第一个元素,会把该元素删除。
System.out.println(linkedDeque.poll());
System.out.println(linkedDeque.peek());
System.out.println(linkedDeque.size());
}
}
执行结果:
2
张三
李四
1
ArrayBlockingQueue
ArrayBlockingQueue 是一个有边界的阻塞队列,它的内部实现是一个数组。有边界的意思是它的容量是有限的,我们必须在其初始化的时候指定它的容量大小,容量大小一旦指定就不可改变。
ArrayBlockingQueue 是一个以先进先出的方式存储数据,最新插入的对象时尾部,最新移出的对象是头部。
代码示例:
package com.test.thread.concurrent.queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.TimeUnit;
/**
* 无界限队列
* Created by husz1 on 2019/4/17.
*/
public class ConcurrentLinkedDequeDemo {
public static void main(String[] args) throws InterruptedException {
ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue(3);
arrayBlockingQueue.add("张三");
arrayBlockingQueue.add("李四");
arrayBlockingQueue.add("王五");
boolean offer = arrayBlockingQueue.offer("王麻子", 2, TimeUnit.SECONDS);
System.out.println(arrayBlockingQueue.size() +"- - - -" + offer);
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
System.out.println(arrayBlockingQueue.poll());
}
}
代码执行结果:
3- - - -false
张三1
李四1
王五1
null
使用并发阻塞队列生产者与消费者
package com.test.thread.concurrent.queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 使用并发阻塞队列实现生产者与消费者
*/
// 生产者队列
class ProducerThread extends Thread {
private BlockingQueue queue;
private boolean flag = true;
private static AtomicInteger count = new AtomicInteger();
public ProducerThread(BlockingQueue queue) {
this.queue = queue;
}
@Override
public void run() {
System.out.println("生产者线程启动。。。");
try {
while (flag) {
System.out.println("正在生产队列。。。");
String data = count.incrementAndGet() + "";
// 添加队列
boolean offer = queue.offer(data);
if (offer) {
System.out.println("生产者添加队列" + data + "成功");
} else {
System.out.println("生产者添加队列" + data + "失败");
}
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("生产线程停止。。。");
}
}
public void stopThread() {
this.flag = false;
}
}
// 消费者
class ConsumerThread extends Thread {
private BlockingQueue queue;
private volatile boolean flag = true;
public ConsumerThread(BlockingQueue queue) {
this.queue = queue;
}
@Override
public void run() {
System.out.println("消费者线程发启动。。。");
try {
while (flag) {
// 保存进去的类型和取出来的类型是一致的
String data = (String)queue.poll(2, TimeUnit.SECONDS);
if(data != null){
System.out.println("消费者获取 data:" + data + "成功");
}else{
System.out.println("消费者获取 data:" +data+ "失败");
this.flag = false;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
System.out.println("消费者停止。。。");
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>(10);
ProducerThread p1 = new ProducerThread(queue);
ProducerThread p2 = new ProducerThread(queue);
ConsumerThread c1 = new ConsumerThread(queue);
p1.start();
p2.start();
c1.start();
// 执行10s
Thread.sleep(10 * 1000);
p1.stopThread();
p2.stopThread();
}
}