多线程 异步模式之生产者/消费者

227 阅读1分钟

image.png

@Slf4j
public class test03 {
    public static void main(String[] args) throws InterruptedException {
        MessageQueue messageQueue = new MessageQueue(2);
        // 4 个生产者线程
        for (int i = 0; i < 4; i++) {
            int id = i;
            new Thread(() -> {
                try {
                    log.debug("download...");
                    List<String> response = List.of("1", "2", "3");
                    log.debug("set message({})", id);
                    messageQueue.set(new Message(id, response));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }, "生产者" + i).start();
        }

        // 1 个消费者线程, 处理结果
        new Thread(() -> {
            while (true) {
                Message message = messageQueue.get();
                List<String> response = (List<String>)message.getMessage();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.debug("get message({}): [{}] lines", message.getId(), response.size());
            }
        }, "消费者").start();

    }
}

@Slf4j
class MessageQueue {
    private final LinkedList<Message> list;

    private final int size;

    public MessageQueue(int size) {
        this.size = size;
        list = new LinkedList<>();
    }

    @SneakyThrows
    public Message get() {
        synchronized (list) {
            while (list.isEmpty()) {
                log.debug("没货了, wait");
                list.wait();
            }
            log.debug("消费");
            Message message = list.removeFirst();
            list.notifyAll();
            return message;
        }
    }

    @SneakyThrows
    public void set(Message message) {
        synchronized (list) {
            while (list.size() >= size) {
                log.debug("库存已达上限, wait");
                list.wait();
            }
            log.debug("加库存");
            list.addLast(message);
            list.notifyAll();
        }

    }
}

record Message(int id, Object message) {

    public int getId() {
        return id;
    }

    public Object getMessage() {
        return message;
    }

    @Override
    public String toString() {
        return "Message{" +
                "id=" + id +
                ", message='" + message + ''' +
                '}';
    }
}