单线程间的通信

x33g5p2x  于2022-03-08 转载在 其他  
字(2.3k)|赞(0)|评价(0)|浏览(118)

一 实战

package concurrent;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

public class EventQueue {
    private final int max;

    static class Event {
    }

    private final LinkedList<Event> evnetQueue = new LinkedList<>();
    private final static int DEFAULT_MAX_EVENT = 10;

    public EventQueue() {
        this(DEFAULT_MAX_EVENT);
    }

    public EventQueue(int max) {
        this.max = max;
    }

    public void offer(Event event) {
        synchronized (evnetQueue) {
            if (evnetQueue.size() >= max) {
                try {
                    System.out.println(" the queue is full");
                    evnetQueue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            System.out.println(" the new event is submitted");
            evnetQueue.addLast(event);
            evnetQueue.notify();
        }
    }

    public Event take() {
        synchronized (evnetQueue) {
            if (evnetQueue.isEmpty()) {
                try {
                    System.out.println("the queue is empty");
                    evnetQueue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            Event event = evnetQueue.removeFirst();
            this.evnetQueue.notify();
            System.out.println("the event" + event + " is handled");
            return event;
        }
    }

    public static void main(String[] args) {
        final EventQueue eventQueue = new EventQueue();
        new Thread(() -> {
            for (; ; ) {
                eventQueue.offer(new EventQueue.Event());
            }
        }, "Producer").start();

        new Thread(() -> {
            for (; ; ) {
                eventQueue.take();
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "Consumer").start();
    }
}

二 测试结果

the new event is submitted
the new event is submitted
the new event is submitted
the new event is submitted
the eventconcurrent.EventQueue$Event@346827f is handled
the new event is submitted
the new event is submitted
the new event is submitted
the new event is submitted
the new event is submitted
the new event is submitted
the new event is submitted
the queue is full
the eventconcurrent.EventQueue$Event@d817c67 is handled
the new event is submitted
the queue is full
the eventconcurrent.EventQueue$Event@9bee90f is handled
the new event is submitted
the queue is full
the eventconcurrent.EventQueue$Event@4cbc765c is handled

三 说明

该例主要用到了 wait 和 notify,使用它们的注意事项如下。

  • wait 方法是可中断方法,这也就意味着,当前线程一旦调用 wait 方法进入阻塞状态,其他线程可以使用 interrupt 方法将其打断,可中断方法被打断后会收到中断异常 InterruptedException,同时中断标识也会被擦除。
  • 线程执行了某个对象的 wait 方法以后,会加入与之对应的 wait set 中,每一个对象的 monitor 都有一个与之关联的 wait set。
  • 当线程进入 wait set 之后,notify 方法可以将其唤醒,也就是从 wait set 中弹出,同时中断 wait 中的线程也会将其唤醒。
  • 必须在同步方法中使用 wait 和 notify 方法,因为执行 wait 和 notify 的前提条件是必须持有同步方法的 monitor 的所有权。
  • 同步代码的 monitor 必要与 wait notify 方法的对象一致,简单地说就是采用哪个对象的 monitor 进行同步,就只能用哪个对象进行 wait 和 notify 操作。

相关文章

微信公众号

最新文章

更多