2.使用 wait notify 实现一个队列,队列有2个方法,add 和 get 。add方法往队列中添加元素,get方法往队列中获得元素。队列必须是线程安全的。如果get执行时,队列为空,线程必须阻塞等待,直到有队列有数据。如果add时,队列已经满,则add线程要等待,直到队列有空闲空间。
/**
* 1.使用 wait notify 实现一个队列,队列有2个方法,add 和 get 。add方法往队列中添加元素,get方法往队列中获得元素。
* 队列必须是线程安全的。如果get执行时,队列为空,线程必须阻塞等待,直到有队列有数据。
* 如果add时,队列已经满,则add线程要等待,直到队列有空闲空间。
* Created by lizq on 2019/4/19.
*/
public class TestMain {
/**
* 锁
*/
private Object lock = new Object();
/**
* 队列
*/
private Queue<Object> list = new LinkedList<Object>();
/**
* 队列的最大长度
*/
private final static int maxLenth = 10;
/**
* 元素
*/
private Integer i = 0;
/**
* 添加元素
*/
public void add() {
while (true) {
// 需要加锁的代码
synchronized (lock) {
// 判断队列的队列
if (list.size() == maxLenth) {
// System.out.println("队列已满请等待!");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("队列满了当前list长度:" + list.size());
lock.notifyAll();
}
} else {
list.add("元素:" + ++i);
System.out.println("加入obj值: " + "元素:" + i +" 当前list长度:" + list.size());
lock.notifyAll();
break;
}
}
}
}
/**
* 获取元素
*
* @return
*/
public Object get() {
while (true) {
synchronized (lock) {
if (list.size() <= 0) {
// System.out.println("没有元素请等待");
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("队列空了当前list长度:" + list.size());
lock.notifyAll();
}
} else {
Object poll = list.poll();
System.out.println("移除obj值: " + poll +" 当前list长度:" + list.size());
lock.notifyAll();
return poll;
}
}
}
}
public static void main(String[] args) {
final TestMain tm = new TestMain();
// 启动5个添加数据线程
for (int i = 0; i < 20; i++) {
new Thread(new Runnable() {
@Override
public void run() {
tm.add();
}
}).start();
}
// 启动5个获取数据线程
for (int i = 0; i < 20; i++) {
new Thread(new Runnable() {
@Override
public void run() {
tm.get();
}
}).start();
}
}
}
结果: