在开发中常常会遇到一些数据量过大的情况因此我们需要阻塞队列来延缓服务器在高峰期接收数据的情况。同时阻塞队列也能做到解耦合的作用防止服务器之间的直接交换。接着就是我们常说的削峰补枯。
成员变量的准备
private String[] data=new String[1000];
private volatile int head=0;
private volatile int tail=0;
private volatile int size=0;
成员变量前面要加上volatile实际上是因为在下面处理高并发的时候可能会遇见你内存可见性的问题,也就是防止编译器优化出现的一系列问题(也就是编译器通过优化使得多个线程之间的数据改动了但是另一个不知道)。
1.阻塞队列的put方法,将数据放入阻塞队列中
public void put(String elem) throws InterruptedException {
synchronized (Myblockingqueue1.class) {
while (size == data.length) {
Myblockingqueue1.class.wait();
}
data[tail]=elem;
tail++;
if (tail==data.length){
tail=0;
}
size++;
Myblockingqueue1.class.notify();
}
}
在这里做一个简要的解释,如果已经放入的数据量等于数组的长度的时候,这个时候我们就进行等待,也就是队列满的时候,最后一个元素如果大于队列长度就将他置为0。
2.阻塞队列的take方法,从阻塞队列中拿取元素
public String take() throws InterruptedException {
synchronized (Myblockingqueue1.class) {
while (size == 0) {
Myblockingqueue1.class.wait();
}
String ret = data[head];
head++;
if (head == data.length) {
head = 0;
}
size--;
Myblockingqueue1.class.notify();
return ret;
}
}
假如队列中为空,这时候就无法拿取元素就要进行等待,至于为什么要用while来,主要是除了notify以外还有一个interrupt可以唤醒,为了防止interrupt唤醒就要通过while来强制wait。
完结附上main方法的调试
public static void main(String[] args) {
//生产者
Myblockingqueue1 myblockingqueue1=new Myblockingqueue1();
Thread thread1=new Thread(()->{
int num=1;
while (true){
try {
myblockingqueue1.put(num+" ");
num++;
System.out.println("生产的数字"+num);
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
//消费者
Thread thread2=new Thread(()->{
while (true) {
try {
String answer = myblockingqueue1.take();
System.out.println("消费的数字" + answer);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
thread1.start();
thread2.start();
}