线程通信-wait(notify)
2019-01-29 本文已影响0人
Coderlifesunny
知识总结
多线程通信最经典的模型就是生产者消费者模式,java中有队列LinkedList可以实现该模式,做到通信协议。
wait和notify(notifyAll)是所有对象的公共方法。
wait和notify必须在同步关键字synchronized代码块中使用。
notify是唤醒应wait等待而进入wait-set集合队列中的队首的线程,notifyALL是唤醒集合队列中所有的线程,然后所有线程任然要同步竞争synchronized(Object)的monitor。
wait与sleep均可以使线程阻塞,sleep只能是线程调用(线程 的方法)。
wait会释放monitor锁,sleep会一直持有。
wait可以不设置等待时间,sleep必须设置等待时间。
撸代码尝试
@Data
@Slf4j
public class EventQueue {
private static final int DEFAULT_MAX_EVENT = 10;
private int max;
private final LinkedList<Event> eventQueue = new LinkedList<>();
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
static class Event {
private String ele;
}
public EventQueue() {
this(DEFAULT_MAX_EVENT);
}
public EventQueue(int max) {
this.max = max;
}
/**
* 往队列里面放数据
*/
public void offer(Event ele) {
synchronized (eventQueue) {
try {
while (eventQueue.size() >= max) {
log.warn("队列已满,请稍后再试试~");
eventQueue.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
eventQueue.addLast(ele);
eventQueue.notifyAll();
log.info("size:" + eventQueue.size() + "成功添加元素:" + ele.getEle());
}
}
/**
* 取队列元素
*
* @return
*/
public Event take() {
synchronized (eventQueue) {
try {
while (eventQueue.isEmpty()) {
log.warn("队列为空,请稍后再试~");
eventQueue.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
Event event = eventQueue.removeFirst();
eventQueue.notifyAll();
log.info("size:" + eventQueue.size() + "成功取出元素:" + event.getEle());
return event;
}
}
public static void main(String[] args) {
EventQueue queue = new EventQueue();
new Thread(() -> {
for (int i = 0; i < Integer.MAX_VALUE; ++i) {
queue.offer(new Event(String.valueOf(i)));
}
}, "Product").start();
new Thread(() -> {
for (; ; ) {
queue.take();
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Consumer").start();
}
}