队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。
顶级接口为java.util.queue.
java.util包中,java.util.concurrent包中有多种实现。其简易类图如下:
在Java并发包中提供了两种类型的队列,非阻塞队列与阻塞队列,它们都是线程安全的(即不能有一个以上的线程同时对队列进行入队或者出队操作),无需担心在多线程并发环境所带来的不可预知的问题。阻塞与否在于是否有界,也就是在初始化时有没有给它一个默认的容量大小。
对于阻塞有界队列来讲,如果队列满了的话,则任何线程都会阻塞不能进行入队操作,反之队列为空的话,则任何线程都不能进行出队操作。
对于非阻塞无界队列来讲则不会出现队列满或者队列空的情况。它们俩都保证线程的安全性。
非阻塞队列:
- ConcurrentLinkedQueue:是一个基于链接节点的无界线程安全队列(java队列ConcurentLinkedQueue)
- PriorityQueue:是一个基于数组实现的队列
阻塞队列:
- ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。(java队列ArrayBlockingQueue)
- LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
- PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
- DealyQueue:一个使用优先级队列实现的无界阻塞队列。
- SynchronousQueue:一个不存储元素的阻塞队列。
- LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
- LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
源码如下:
package java.util;
public interface Queue<E> extends Collection<E> {
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
}
------------------------自己实现的一个阻塞队列----------------------------------------------------------------------------
import java.util.ArrayList;
import java.util.List;
/**
* @author Qiaofan
* @create 2018-10-10 16:31
* 自定义线程安全的阻塞队列
**/
public class MyBlockingQueue {
public MyBlockingQueue(Integer maxSize) {
this.maxSize = maxSize;
myQueue = new ArrayList<>(maxSize);
System.out.println("队列初始化,池大小"+maxSize);
}
//队列大小
private Integer maxSize;
private List<String> myQueue;
//自定义对象锁
private Object lock = new Object();
/**
* 出队方法
*/
public void get(){
synchronized(lock) {
try {
if(myQueue.size() == 0){
System.out.println("队列空了,线程"+Thread.currentThread().getName()+"等待...");
lock.wait();
}else{
String str=this.myQueue.get(0);
myQueue.remove(0);
System.out.println("线程"+Thread.currentThread().getName()+"获取元素:"+str);
}
lock.notifyAll();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
/**
* 入队方法
* @param str
*/
public void put(String str){
synchronized (lock){
try {
if(myQueue.size() == maxSize){
System.out.println("队列满了,线程"+Thread.currentThread().getName()+"等待...");
lock.wait();
}else{
System.out.println("线程"+Thread.currentThread().getName()+"添加元素:"+str);
myQueue.add(str);
}
lock.notifyAll();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
测试的main方法
public static void main(String[] args){
MyBlockingQueue myBlockingQueue = new MyBlockingQueue(10);
Thread t3= new Thread(new Runnable() {
@Override
public void run() {
try{
for (int i = 0; i < 10; i++) {
myBlockingQueue.put("T3-"+i);
Thread.sleep(200);
}
}catch (Exception e){
e.printStackTrace();
}
}
},"T3-");
Thread t4= new Thread(new Runnable() {
@Override
public void run() {
try{
for (int i = 0; i < 10; i++) {
myBlockingQueue.put("T4-"+i);
Thread.sleep(200);
}
}catch (Exception e){
e.printStackTrace();
}
}
},"T4-");
Thread t2= new Thread(new Runnable() {
@Override
public void run() {
try{
while (true){
myBlockingQueue.get();
Thread.sleep(100);
}
}catch (Exception e){
e.printStackTrace();
}
}
},"T2-");
Thread t1= new Thread(new Runnable() {
@Override
public void run() {
try{
while (true){
myBlockingQueue.get();
Thread.sleep(100);
}
}catch (Exception e){
e.printStackTrace();
}
}
},"T1-");
t3.start();
t4.start();
t1.start();
t2.start();
}