使用 wait notify 实现一个队列,队列有2个方法,add 和 get 。add方法往队列中添加元素,get方法往队列中获得元素。队列必须是线程安全的。如果get执行时,队列为空,线程必须阻塞等待,直到有队列有数据。如果add时,队列已经满,则add线程要等待,直到队列有空闲空间。
/**
* 使用LinkedList实现安全队列
*
*/
public class SafeLinkedList<E> {
private LinkedList<E> data = new LinkedList<>();
private int totalSize;
public SafeLinkedList(int totalSize) {
this.totalSize = totalSize;
}
/**
* 当队列已满时候,阻塞,直到取走数据为止
* @param e
*/
public void add(E e) {
synchronized (data) {
if (data.size() == totalSize) {
try {
data.wait();
} catch (InterruptedException e1) {
Thread.interrupted();
data.notifyAll();
System.out.println("队列已满啦!");
}
}
data.add(e);
data.notifyAll();
}
}
/**
* 当队列为空时候,阻塞等待
* @return
*/
public E get() {
synchronized (data) {
if (data.isEmpty()) {
try {
data.wait();
} catch (InterruptedException e) {
Thread.interrupted();
data.notifyAll();
}
}
E e = data.getFirst();//获取队列头元素
data.removeFirst();//移除对头元素
data.notifyAll();
return e;
}
}
public synchronized int size() {
return data.size();
}
}
测试队列:
/**
* 多线程条件下测试LinkedList存取数据是否安全
*/
public class SafeLinkedListTest {
private SafeLinkedList<String> data = new SafeLinkedList<>(10);
@Test
public void putGetTest() throws InterruptedException {
//add test
Thread t1 = new Thread(new OperAddThread());
Thread t2 = new Thread(new OperAddThread());
Thread t3 = new Thread(new OperAddThread());
Thread getThread = new Thread(new OperGetThread());
getThread.setName("getThread");
t1.start();
t2.start();
t3.start();
getThread.start();
t1.join();
t2.join();
t3.join();
getThread.join();
System.out.println(data.size());
}
class OperAddThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 4; i++) {
String addData=Thread.currentThread().getName()+"|"+String.valueOf(i);
data.add(addData);
System.out.println("add size=" + data.size());
System.out.println(Thread.currentThread().getName() + " addData=" + addData);
}
}
}
class OperGetThread implements Runnable {
@Override
public void run() {
int i=11;
while (i>=0) {
i--;
String value = data.get();
System.out.println("get size=" + data.size());
System.out.println("get string--" + " ;value=" + value);
}
}
}
}