Java并行程序设计模式——Guarded Suspension模式

问题引出

假如说你的服务器在很短时间内承受了大量的客户端请求(如果这是你朋友用Python搞你的话请好好打他一顿),客户端请求量可能超过了服务器本身的即时处理量,而服务端程序又不能丢弃任何一个客户请求,应该怎么办?

答:最佳处理方案莫过于让客户端排队请求进行排队,由服务端程序一个个处理。这样既保证了所有的客户端请求均不丢失,同时也避免了服务器由于同时处理太多的请求而崩溃。这就是Guarded Suspension模式

Guarded Suspension模式

Guarded是“被保护着的”、“被防卫着的”意思,Suspension则是“暂停”的意思。
Guarded Suspension意为保护暂停,其核心思想是仅当服务进程准备好时,才提供服务。

在这里插入图片描述

角色 作用
Request 表示客户端请求
RequestQueue 用于保存客户端的请求的队列,充当中间缓存,由ClientThread和ServerThread 共同维护
ClientThread 客户端进程,用于发送请求并把请求对象放入请求队列
ServerThread 服务器进程,根据自身状态,在有能力处理请求时,从请求队列中提取请求对象加以处理
// 一个POJO对象,封装了请求的内容
public class Request {
    private String name;

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

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Request{" +
                "name='" + name + '\'' +
                '}';
    }
}
// Request的集合,维护系统的Request请求列表
public class RequestQueue {
    private LinkedList queue = new LinkedList();

    public synchronized Request getRequest() {
        while (queue.size() == 0) {
            try {
                wait();                        // 等待直到有新的Request加入
            } catch (InterruptedException e) {

            }
        }
        return (Request)queue.remove();     // 返回Request队列中的第一个请求
    }

    public synchronized void addRequest(Request request) {
        queue.add(request);                 // 加入新的Request请求
        notifyAll();                         // 通知getRequest()方法
    }
}
//  服务端进程代码,用于处理用户的请求操作
public class ServerThread extends Thread {
    private RequestQueue requestQueue;          //  请求队列

    public ServerThread(RequestQueue requestQueue, String name) {
        super(name);
        this.requestQueue = requestQueue;
    }

    @Override
    public void run() {
        while (true) {
            final Request request = requestQueue.getRequest();      // 得到请求
            try {
                Thread.sleep(100);                          // 模拟请求处理耗时
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " handles " + request);
        }
    }
}
// 客户端的请求发起进程
public class ClientThread extends Thread {
    private RequestQueue requestQueue;                      // 请求队列

    public ClientThread(RequestQueue requestQueue, String name) {
        super(name);
        this.requestQueue = requestQueue;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            Request request = new Request("RequestID:" + i + " Thread_Name:" + Thread.currentThread().getName());   // 构造请求
            System.out.println(Thread.currentThread().getName() + " requests " + request);
            requestQueue.addRequest(request);           // 提交请求
            try {
                Thread.sleep(10);               // 模拟客户端请求的速度,快于服务端处理速度
            } catch (InterruptedException e) {

            }
            System.out.println("ClientThread Name is:" + Thread.currentThread().getName());
        }
        System.out.println(Thread.currentThread().getName() + " request end");
    }
}
// 主函数
public class Main {
    public static void main(String[] args) {
        RequestQueue requestQueue = new RequestQueue();
        for (int i = 0; i < 10; i++) {
            new ServerThread(requestQueue, "ServerThread" + i).start();
        }
        for (int i = 0; i < 10;i++) {
            new ClientThread(requestQueue, "ClientThread" + i).start();
        }
    }
}

在这里插入图片描述分析
开启了10个Client和Server进程,每个Client进程发送10个请求。由于Client进程的请求速度快于Server的处理速度,因此RequestQueue起到了中间缓存作用。当所有Client进程结束后,Server进程并没有停止工作,而是继续处理RequestQueue的请求,直至所有Request请求均得到处理

扩展——携带返回结果的Guarded Suspension

未完待续。。。

发布了37 篇原创文章 · 获赞 16 · 访问量 6044

猜你喜欢

转载自blog.csdn.net/qq_44039966/article/details/103357538