阻塞队列是带有阻塞功能且线程安全的队列.(即,队列为空,尝试出队列,出队列操作就会阻塞等待一直阻塞到队列不为空为止,队列为满,入队操作就会阻塞等待一直阻塞到队列不满为止.) 阻塞队列的作用之一就是可以实现生产者消费者模型,有两方面的作用1.能够让程序解耦合 2.能够实现"削峰填谷".
首先使用标准库提供的阻塞队列.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Demo1 {
public static void main(String[] args){
BlockingQueue<Integer> queue=new ArrayBlockingQueue<>(10);
//消费者
//put带有阻塞功能的入队列 take带有阻塞功能的出队列
Thread t1=new Thread(()->{
while(true) {
int value;
try {
value = queue.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("消费的:" + value);
}
});
Thread t2=new Thread(()-> {
int count=1;
while (true) {
try {
queue.put(count);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("生产的:"+count);
count++;
}
});
t1.start();
t2.start();
}
}
//由于对生产和消费没有限制虽然限制了队列的大小是10,所以没有体现出阻塞功能.
import java.sql.SQLOutput;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Demo2 {
public static void main(String[] args){
BlockingQueue<Integer> queue=new ArrayBlockingQueue<>(10);
//生产者
Thread t1=new Thread(()->{
int count=1;
while(true){
try {
queue.put(count);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("生产者:"+count);
count++;
}
//如果对消费者的速度进行限制,那么会使阻塞队列满
});
//消费者
Thread t2=new Thread(()->{
int value;
while(true){
try {
value=queue.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("消费者:"+value);
}
});
//这里消费者是一秒钟消费一次,因此在进行出队列的时候会发生阻塞
//且队列中只有10个元素.
t1.start();
t2.start();
}
}
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Demo3 {
public static void main(String[] args){
BlockingQueue<Integer> queue=new ArrayBlockingQueue<>(10);
Thread t1=new Thread(()->{
int count=1;
while(true) {
try {
queue.put(count);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("生产者:"+ count);
count++;
}
});
Thread t2=new Thread(()->{
int value;
while(true){
try {
value=queue.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("消费者:"+value);
}
});
//这一次是没有对生产者进行限制,因此消费者的节奏会跟着生产者.
t1.start();
t2.start();
}
}
接下来自己实现一个带有阻塞功能的队列.
//自己实现阻塞队列
class MyblockingQueue{
//自己实现阻塞队列
//设置一个队列是存储整形的
private int[] elems=null;
//[head,tail)
//head是头结点,tail是尾结点
//开始的时候,头结点和尾结点都是0,size也是0
private int head=0;
private int tail=0;
private int size=0;
//构造方法
public MyblockingQueue(int capacity){
elems=new int[capacity];
}
//下面写入队列操作
void put(int elem) throws InterruptedException {
//首先要判断队列是否满
synchronized(this) {
while (size >= elems.length) {
this.wait();
//如果队列满了就要进行阻塞操作
//一定要进行返回等待,等待出队列操作的执行
return;
}
//队列没有满入队列时
//尾结点指向的空间没有存储元素
elems[tail] = elem;
tail++;
if (tail >= elems.length) {
tail = 0;
//到达了队列的末尾就要回到开头
}
size++;
this.notify();
}
}
//出队列操作
int take() throws InterruptedException {
synchronized(this) {
//还是要先判断队列是否是空,如果为空,就要阻塞等待
while (size == 0) {
this.wait();
return -99999;
}
//出队列操作
int result = elems[head];
head++;
if (head >= elems.length) {
head = 0;
}
size--;
this.notify();
return result;
}
}
}
public class Demo2 {
public static void main(String[] args) {
MyblockingQueue tt=new MyblockingQueue(10);
Thread t1=new Thread(()->{
int count=0;
while(true){
try {
tt.put(count);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("生产者: "+count);
count++;
}
});
Thread t2=new Thread(()->{
int value;
while(true){
try {
value=tt.take();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("消费者: "+value);
}
});
t1.start();
t2.start();
}
}