多執行緒設計模式-高併發請求快取模式(Guarded Suspension)

睡醒的土豆發表於2021-01-03

高併發請求快取佇列設計模式

一,什麼是Guarded Suspension模式
如果執行現在的處理會造成問題,就讓執行處理的執行緒等待。這種模式通過讓執行緒等待來保證例項的安全性

二,實現一個簡單的執行緒間通訊的例子

一個執行緒(ClientThread)將請求(Request)的例項傳遞給另外一個執行緒(ServerThread)

Request:執行緒例項

RequestQueue:存放請求(Request)例項的佇列

ClientThread:把執行緒例項放到佇列中

ServerThread:從佇列中取執行緒示例

示例程式

package com.ln.concurrent.chapter9;

/**
 * @ProjectName: java-concurrency
 * @Package: com.ln.concurrent.chapter9
 * @Name:Request
 * @Author:linianest
 * @CreateTime:2020/3/28 19:29
 * @version:1.0
 * @Description TODO: Request請求
 */
public class Request {
    private final String value;

    public Request(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

請求佇列

package com.ln.concurrent.chapter9;

import java.util.LinkedList;

/**
 * @ProjectName: java-concurrency
 * @Package: com.ln.concurrent.chapter9
 * @Name:RequestQueue
 * @Author:linianest
 * @CreateTime:2020/3/28 19:31
 * @version:1.0
 * @Description TODO: 請求佇列
 */
public class RequestQueue {
    private final LinkedList<Request> queue = new LinkedList<>();

    public Request getRequest() {
        synchronized (queue) {
            while (queue.size() <= 0) {
                try {
                    queue.wait();
                } catch (InterruptedException e) {
                    return null;
                }
            }
            return queue.removeFirst();
        }

    }

    public void putRequest(Request request) {
        synchronized (queue) {
            queue.addLast(request);
            queue.notifyAll();
        }
    }
}

請求客戶端執行緒

package com.ln.concurrent.chapter9;

import java.util.Random;

/**
 * @ProjectName: java-concurrency
 * @Package: com.ln.concurrent.chapter9
 * @Name:ClientThread
 * @Author:linianest
 * @CreateTime:2020/3/28 19:55
 * @version:1.0
 * @Description TODO: 客戶端執行緒
 */
public class ClientThread extends Thread{
    private final RequestQueue queue;

    private final Random random;
    private final String sendValue;

    public ClientThread(RequestQueue queue, String sendValue){
        this.queue = queue;
        this.sendValue = sendValue;
        this.random = new Random(System.currentTimeMillis());
    }

    @Override
    public void run() {
        for (int i = 0; i < 10 ; i++) {
           System.out.println("Client -> Request "+sendValue);
           queue.putRequest(new Request(sendValue));
            try {
                Thread.sleep(random.nextInt(1_000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

服務端處理執行緒

package com.ln.concurrent.chapter9;

import java.util.Random;

/**
 * @ProjectName: java-concurrency
 * @Package: com.ln.concurrent.chapter9
 * @Name:ServerThread
 * @Author:linianest
 * @CreateTime:2020/3/28 20:03
 * @version:1.0
 * @Description TODO: 服務端處理執行緒
 */
public class ServerThread extends Thread {

    private final RequestQueue queue;

    private final Random random;

    private volatile boolean closed = false;

    public ServerThread(RequestQueue queue) {
        this.queue = queue;
        this.random = new Random(System.currentTimeMillis());
    }


    @Override
    public void run() {
        while (!closed) {
            Request request = queue.getRequest();
            if (null == request) {
                System.out.println("Received the empty request.");
                continue;
            }
            System.out.println("Server -> " + request.getValue());
            try {
                Thread.sleep(random.nextInt(1_000));
            } catch (InterruptedException e) {
                return;
            }
        }
    }

    public void close() {
        this.closed = true;
        this.interrupt();
    }
}

高併發請求,快取佇列

package com.ln.concurrent.chapter9;

/**
 * @ProjectName: java-concurrency
 * @Package: com.ln.concurrent.chapter9
 * @Name:SuspensionClient
 * @Author:linianest
 * @CreateTime:2020/3/28 20:20
 * @version:1.0
 * @Description TODO: 高併發請求,快取佇列
 */
public class SuspensionClient {
    public static void main(String[] args) throws InterruptedException {
        final RequestQueue queue = new RequestQueue();
        new ClientThread(queue, "Alex").start();
        ServerThread serverThread = new ServerThread(queue);
        serverThread.start();
//        serverThread.join();

        Thread.sleep(10000);

        serverThread.close();
    }
}

這種實現了,將高併發請求快取在佇列中,當前面的任務執行緒執行完成後,按照順序執行快取的任務請求,保護伺服器

相關文章