如题:
使用 wait notify 实现一个队列,队列有2个方法,add 和 get 。add方法往队列中添加元素,get方法往队列中获得元素。队列必须是线程安全的。如果get执行时,队列为空,线程必须阻塞等待,直到有队列有数据。如果add时,队列已经满,则add线程要等待,直到队列有空闲空间。
实现这么一个队列,并写一个测试代码,使他工作在多线程的环境下,证明,它的工作是正确的。给出程序和运行的截图。
Queue: 基本上,一个队列就是一个先入先出(FIFO)的数据结构
Queue接口与List、Set同一级别,都是继承了Collection接口。LinkedList实现了Deque接 口。
Queue的实现
1、没有实现的阻塞接口的LinkedList: 实现了java.util.Queue接口和java.util.AbstractQueue接口
内置的不阻塞队列: PriorityQueue 和 ConcurrentLinkedQueue
PriorityQueue 和 ConcurrentLinkedQueue 类在 Collection Framework 中加入两个具体集合实现。
PriorityQueue 类实质上维护了一个有序列表。加入到 Queue 中的元素根据它们的天然排序(通过其 java.util.Comparable 实现)或者根据传递给构造函数的 java.util.Comparator 实现来定位。
ConcurrentLinkedQueue 是基于链接节点的、线程安全的队列。并发访问不需要同步。因为它在队列的尾部添加元素并从头部删除它们,所以只要不需要知道队列的大 小, ConcurrentLinkedQueue 对公共集合的共享访问就可以工作得很好。收集关于队列大小的信息会很慢,需要遍历队列。
2)实现阻塞接口的:
java.util.concurrent 中加入了 BlockingQueue 接口和五个阻塞队列类。它实质上就是一种带有一点扭曲的 FIFO 数据结构。不是立即从队列中添加或者删除元素,线程执行操作阻塞,直到有空间或者元素可用。
五个队列所提供的各有不同:
* ArrayBlockingQueue :一个由数组支持的有界队列。
* LinkedBlockingQueue :一个由链接节点支持的可选有界队列。
* PriorityBlockingQueue :一个由优先级堆支持的无界优先级队列。
* DelayQueue :一个由优先级堆支持的、基于时间的调度队列。
* SynchronousQueue :一个利用 BlockingQueue 接口的简单聚集(rendezvous)机制。
add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞
remove、element、offer 、poll、peek 其实是属于Queue接口。
先添加三个类,在运行main方法验证:
ps:当时想把其他两个类都写在一起遇到错误,最后分开写,实例化不会出问题;
enclosing instance of type ThreadQueue (e.g. x.new A() where x is an instance of ThreadQueue)
解释地址:https://blog.csdn.net/u012965373/article/details/41488695
package com.cdy.mvc.threadtest;
import java.util.LinkedList;
import java.util.Queue;
public class ThreadQueue extends Thread{
private static final int maxLenth = 10;
static Object lock = new Object();
private Integer i = 0;
private Queue<Object> queue = new LinkedList<Object>();
public void add() {
synchronized (lock) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (queue.size() == maxLenth) {
try {
System.out.println("队列满了当前list长度:" + queue.size());
lock.wait();
} catch (InterruptedException e) {
System.out.println("队列满了当前list长度:" + queue.size());
e.printStackTrace();
}
}
queue.add(i++);
System.out.println("放入队列成功" + i);
lock.notifyAll();
}
}
public Integer get() {
synchronized (lock) {
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(queue.size()==0){
try {
System.out.println("队列空了当前list长度:"+queue.size());
lock.wait();
} catch (InterruptedException e) {
System.out.println("队列空了当前list长度:"+queue.size());
lock.notifyAll();
}
return null;
}
Integer poll = (Integer) queue.poll();
System.out.println("移除i值:"+poll);
lock.notifyAll();
return poll;
}
}
public static void main(String[] args) {
ThreadQueue queue = new ThreadQueue();
Thread add1 = new AddThread(queue,"生产者1");
Thread add2 = new AddThread(queue,"生产者2");
Thread add3 = new AddThread(queue,"生产者3");
Thread get1 = new GetThread(queue,"消费者1");
Thread get2 = new GetThread(queue,"消费者2");
add1.start();add2.start();add3.start();
get1.start();get2.start();
}
}
package com.cdy.mvc.threadtest;
public class AddThread extends Thread{
ThreadQueue q;
public AddThread(ThreadQueue q,String name){
super(name);
this.q = q;
}
@Override
public void run() {
for(int i=0;i<4;i++){
q.add();
}
}
}
package com.cdy.mvc.threadtest;
public class GetThread extends Thread {
ThreadQueue q;
public GetThread(ThreadQueue q,String name){
super(name);
this.q = q;
}
@Override
public void run() {
while(true){
q.get();
}
}
}
测试结果:
放入队列成功1
放入队列成功2
放入队列成功3
放入队列成功4
移除i值:0
移除i值:1
移除i值:2
移除i值:3
队列空了当前list长度:0
队列空了当前list长度:0
放入队列成功5
放入队列成功6
放入队列成功7
放入队列成功8
放入队列成功9
放入队列成功10
放入队列成功11
放入队列成功12
移除i值:4
移除i值:5
移除i值:6
移除i值:7
移除i值:8
移除i值:9
移除i值:10
移除i值:11
队列空了当前list长度:0
队列空了当前list长度:0