并发队列
在并发队列上JDK提供了两套实现,一个是以ConcurrentLinkedQueue为代表的高性能队非阻塞队列,一个是以BlockingQueue接口为代表的阻塞队列,无论哪种都继承自Queue。
阻塞队列与非阻塞队
阻塞队列与普通队列的区别在于,当队列是空的时候,从队列中获取元素的操作将会被阻塞或者当队列是满的情况下往队列中添加内容他也会被阻塞
ConcurrentLinkedQueue
非阻塞式队列ConcurrentLinkedQueue : 是一个适用于高并发场景下的队列,通过无锁的方式,实现了高并发状态下的高性能,通常ConcurrentLinkedQueue性能好于BlockingQueue.它是一个基于链接节点的无界线程安全队列。该队列的元素遵循先进先出的原则。头是最先加入的,尾是最近加入的,该队列不允许null元素。
BlockingQueue
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:
在队列为空时,获取元素的线程会等待队列变为非空。
当队列满时,存储元素的线程会等待队列可用。
阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。
BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种:
1. 当队列满了的时候进行入队列操作
2. 当队列空了的时候进行出队列操作
因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空队列进行出队列操作时,它将会被阻塞,除非有另一个线程进行了入队列操作。
通过阻塞队列实现生产者消费者
package com.dapao.Quqe;
import com.sun.xml.internal.ws.util.StreamUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 生产者
*
* @Author ffc
* @Date: 2019/12/5 15:20
**/
class ProducerThread implements Runnable {
/**
* 定义一个阻塞队列
**/
private BlockingQueue<String> blockingQueue;
/**
* 定义一个判读那条件 volatile支持可见性和禁止重排序
**/
private volatile boolean FLAG = true;
/**
* 进行计数,AtomicInteger他保证线程安全
**/
AtomicInteger atomicInteger = new AtomicInteger();
public ProducerThread( BlockingQueue<String> blockingQueue ) {
this.blockingQueue = blockingQueue;
}
public void run() {
System.out.println("生产者已经开始生产了");
try {
while (FLAG) {
String data = String.valueOf(atomicInteger.incrementAndGet());
// 往队列添加数据
boolean offer = blockingQueue.offer(data, 2, TimeUnit.SECONDS);
if (offer) {
System.out.println("生产者添加到队列中 data" + data);
} else {
System.out.println("生产者添加到队列失败 data" + data);
}
Thread.sleep(1000);
}
} catch (Exception e) {
} finally {
System.out.println("生产者结束了");
}
}
}
class ConsumerThread implements Runnable {
/**
* 定义一个阻塞队列
**/
private BlockingQueue<String> blockingQueue;
/**
* 定义一个判读那条件 volatile支持可见性和禁止重排序
**/
private volatile boolean FLAG = true;
/**
* 进行计数,AtomicInteger他保证线程安全
**/
AtomicInteger atomicInteger = new AtomicInteger();
public ConsumerThread( BlockingQueue<String> blockingQueue ) {
this.blockingQueue = blockingQueue;
}
public void run() {
System.out.println(Thread.currentThread().getName() + "消费者开始启动....");
try {
while (FLAG) {
String data = blockingQueue.poll(2, TimeUnit.SECONDS);
if (StringUtils.isEmpty(data)) {
FLAG = false;
System.out.println("消费者超过2秒时间未获取到消息.");
return;
}
System.out.println("消费者获取到队列信息成功,data:" + data);
Thread.sleep(1000);
}
} catch (Exception e) {
} finally {
System.out.println("消费者已经结束了");
}
}
}
/**
* @Author: ffc
* @Date: 2019/12/5 15:20
*/
public class Test004 {
public static void main( String[] args ) {
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
BlockingQueue<String> objects = new LinkedBlockingQueue<String>(10);
ProducerThread producerThread = new ProducerThread(objects);
ConsumerThread consumerThread = new ConsumerThread(objects);
newCachedThreadPool.execute(producerThread);
newCachedThreadPool.execute(consumerThread);
try {
Thread.sleep(10 * 1000);
} catch (Exception e) {
}
}
}