说到队列,第一反应就是MQ..- -.MQ是一种队列,市面上也有各种MQ,比如Rabbit,Rocket,Active,Kafka等.语言千奇百怪,消息中间件技术千奇百怪,但是总是有一个核心的设计也就是队列.
ConcurrentLinkedQueue:
一个线程安全的高性能无界队列,常用的方法有poll , peek , offer , add.
poll:从队列的头部获取到元素 , 获取到之后将其移除
peek:从队列的头部获取到元素 , 获取到之后依旧存在
offer和add在这里都是添加到队列尾部,没有什么实质区别
如图:
这里new了一个ConcurrentLinkedQueue,并且添加了4个元素,再来比较一下peek和poll.查看运行结果可以验证我的说明.
如图:
最近身体有点问题..未完待续
Fine 终于有时间来补全一下 自从UUMQ(原来的MQ4JJ)在Github上删了仓库之后算是对之前的编码生涯的一次告别.哀莫大于心死啊.
不管前路如何多艰 江山依然如此多娇嘛
心情好 来模拟一下阻塞队列的实现吧.直接上代码
public class MyQueueDemo {
private LinkedList<Object> list = new LinkedList<>();
/**
* count是一个AtomicInteger
* AtomicInteger提供原子操作来进行Integer的使用,在高并发的环境下十分适合
* AtomicInteger的源码中的成员变量value(int) 被volatile修饰 可以使多个线程共享此变量
* 但是volatile的使用会使得JVM对于多线程的某些优化失效 所以根据场景谨慎使用
*/
private AtomicInteger count = new AtomicInteger();
/**
* maxSize和minSize是模拟阻塞队列中计数器的最大最小值(默认0)
*/
private int maxSize;
private int minSize = 0;
/**
* 定义Object类对象lock 作为同步方法中的锁(对象锁)
*/
private final Object lock = new Object();
/**
* 构造方法
* @param maxSize 队列的最大容量
*/
private MyQueueDemo(int maxSize) {
this.maxSize = maxSize;
}
/**
* 队列的put方法 存放对象
* @param object 往LinkedList<Object>中存放的对象
*/
public void put(Object object) {
synchronized (lock) {
/*
* 当队列中的容量已经到达maxSize lock.wait() 线程等待并且释放锁
*/
while (count.get() == maxSize) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*
* 没有到达最大容量时 往list中添加元素 计数器+1
* AtomicInteger的getAndIncrement()是线程安全的 ++ 则不安全
*/
list.add(object);
count.getAndIncrement();
System.out.println("元素: " + object + " 加入");
//notify不会立刻释放锁 需要等待notify所在线程执行完毕后才能释放
lock.notify();
}
}
/**
* 队列的take方法 获取对象
* @return take到的对象
*/
public Object take() {
Object temp;
synchronized (lock) {
/*
* 如果容器大小为minSize 容器为空 lock.wait() 阻塞 释放同步锁
*/
while (count.get() == minSize) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*
* AtomicInteger中的getAndDecrement()线程安全 -- 则不安全
*/
count.getAndDecrement();
temp = list.removeFirst();
System.out.println("元素:" + temp + " 消费");
lock.notify();
}
return temp;
}
/**
* 获取队列的大小
* @return 队列计数器当前值
*/
public int size() {
return count.get();
}
public static void main(String[] args) throws InterruptedException {
int queueSize = 10;
MyQueueDemo queue = new MyQueueDemo(10);
for(int i = 0 ; i < queueSize ; i++) {
queue.put(i);
}
System.out.println("当前元素个数: " + queue.size());
Thread t1 = new Thread(() -> {
queue.put(123);
queue.put(456);
queue.put(678);
} , "Thread1");
Thread t2 = new Thread(() -> {
try {
Thread.sleep(1000);
Object get1 = queue.take();
Thread.sleep(1000);
Object get2 = queue.take();
Thread.sleep(3000);
Object get3 = queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
} , "Thread2");
t1.start();
Thread.sleep(1000);
t2.start();
}
是不是十分简单