多線程之模擬自定義消息隊列

1.背景

面試官問,假設讓你設計一個隊列,你的思路是...

2.代碼

package com.ldp.demo01;

import com.common.MyThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;

/**
 * @author 姿勢帝-博客園
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 01/31 8:24
 * @description
 */
@Slf4j
public class Test08MessageQueue {
    /**
     * 測試自定義的隊列
     *
     * @param args
     */
    public static void main(String[] args) {
        // 創建隊列
        MessageQueue queue = new MessageQueue(2);
        // 模擬4個生產者參數數據到隊列
        for (int i = 0; i < 4; i++) {
            int n = i + 1;
            new Thread(() -> {
                int m = 1;
                // 不停的循環放入數據
                while (true) {
                    int k = n * 1000 + m;
                    Message message = new Message(k, "消息-" + k);
                    log.info("放入的消息是:{}", message);
                    queue.put(message);
                    m++;
                }
            }, "生產者-" + n).start();
        }
        // 模擬2個消費者到隊列中取數據
        for (int i = 0; i < 1; i++) {
            int n = i + 1;
            new Thread(() -> {
                // 每個消費者都是不停的取數據
                while (true) {
                    // 每隔2秒取一次
                    MyThreadUtil.sleep(2);
                    Message message = queue.take();
                    log.info("取到的消息是:{}", message);
                }
            }, "消費者-" + n).start();
        }
    }
}

@Slf4j
class MessageQueue {
    /**
     * 隊列的容量
     */
    private Integer capacity;
    /**
     * 裝消息的隊列
     */
    private LinkedList<Message> list = new LinkedList<>();

    public MessageQueue(Integer capacity) {
        this.capacity = capacity;
    }

    /**
     * 獲取一條消息
     *
     * @return
     */
    public Message take() {
        synchronized (list) {
            while (list.isEmpty()) {
                try {
                    // log.debug("無數據,等待中....");
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 取出頭部消息,並刪除
            Message message = list.removeFirst();
            // 通知放入隊列
            list.notifyAll();
            return message;
        }
    }

    /**
     * 放入一條數據
     *
     * @param message
     */
    public void put(Message message) {
        synchronized (list) {
            while (list.size() >= capacity) {
                try {
                    //  log.debug("隊列已滿,當前隊列數:{},最大隊列數:{}", list.size(), capacity);
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 放入隊列
            list.addLast(message);
            // 通知消費者取數據
            list.notifyAll();
        }
    }
}

/**
 * 消息對象
 * 使用final不讓其被繼承,避免修改消息
 */
final class Message {
    private Integer id;
    private Object object;

    /**
     * 提供一個構造方法
     *
     * @param id
     * @param object
     */
    public Message(Integer id, Object object) {
        /**
         * 消息id
         */
        this.id = id;
        /**
         * 具體的消息內容
         */
        this.object = object;
    }

    /**
     * 只提供獲取方法,讓消息不可以修改
     *
     * @return
     */
    public Integer getId() {
        return id;
    }

    public Object getObject() {
        return object;
    }

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

 

完美

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章