1、简介与说明
这里主要是利用数组,实现一个线程安全的有界队列,不支持扩容。
- 数据结构:这里使用的数组
- 算法:FIFO,遵循队列先进先出原则
- 线程安全:利用synchronized关键字加锁以及线程之间通讯确保队列安全
2、具体代码实现
1、有界队列
/**
* 定义一个线程安全有界消息队列
* 1、数据结构:数组
* 2、具体算法:FIFO,先进先出
*/
public class BlockContainer<T> {
private Object[] array;
private int size;
/**
* 提供带参构造
*
* @param cap
*/
public BlockContainer(int cap) {
array = new Object[cap];
}
/**
* 提供默认构造,默认大小16
*/
public BlockContainer() {
this(16);
}
/**
* 生产者线程通过put方法向队列存放消息
* 数据永远放在size位置
* 实力方法内部的this永远指向调用此方法的当前对象
* 静态方法中没有this,this只能应用在实例方法,构造方法,实例代码块中
*/
public synchronized void put(T t) {
//1、判断队列大小是不是满了,满了的话就不接收消息了
while (size == array.length) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2、如果队列没有满,放入数据
array[size] = t;
//3、有效元素个数加一
size++;
//4、通知消费者取数据
this.notifyAll();
}
/**
* 消费者通过此方法取数据
* 永远取下标为0的位置的数据
*
* @return
*/
public synchronized T take() {
//1、判断当前容器是否为空
while (size == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//2、取数据
Object obj = array[0];
//3、移动元素
System.arraycopy(
array, //原数组
1,//从哪个位置开始拷贝
array,//放到哪个数组
0,//从哪个位置开始放
size - 1);//拷贝几个
//4、队列有效个数减一
size--;
//5、将size位置的值置为null
array[size] = null;
//6、唤醒所有线程取数据
this.notifyAll();
return (T) obj;
}
@Override
public String toString() {
return "BlockContainer{" +
"array=" + Arrays.toString(array) +
", size=" + size +
'}';
}
}
2、测试
/**
* 测试多线程情况下的队列
*/
public class Test02 {
static class Producer extends Thread {
private BlockContainer<Object> blockContainer;
public Producer(BlockContainer<Object> blockContainer) {
this.blockContainer = blockContainer;
}
@Override
public void run() {
int i = 1;
while (true) {
blockContainer.put(i);
System.out.println("往队列中放入消息:[" + i + "]");
i++;
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Consumer extends Thread {
private BlockContainer<Object> blockContainer;
public Consumer(BlockContainer<Object> blockContainer) {
this.blockContainer = blockContainer;
}
@Override
public void run() {
while (true) {
Object result = blockContainer.take();
System.out.println("往队列中取出消息:[" + result + "]");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
BlockContainer<Object> c = new BlockContainer<>();
Producer producer = new Producer(c);
Consumer consumer = new Consumer(c);
producer.start();
consumer.start();
}
}
最后,有好的想法和意见欢迎大家一起交流。