JAVA自我总结

线程通信-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();
    }


}
上一篇下一篇

猜你喜欢

热点阅读