有时候我们需要避免突然出现太多的请求而导致服务器奔溃,但同时又需要保证用户的请求不丢失,在这里我们可以借鉴一下Guarded Suspension模式
原理
Guarded Suspension模式原理很简单,当大量访问同时进来时,我们需要将这些请求缓存起来,然后让服务器逐步消化,同时为了保证用户端有反馈,以至于不断的重刷加重服务器的负载,我们可以借鉴Future模式
模拟角色
- ClientThread:客户端访问模拟
- ServerThread:服务器处理模拟
- RequestQueue:发送的消息类
代码
代码很简单,思想也很简单,就是在请求时候加一个缓存,好吧,下面开始看代码吧!
- RequestQueue:消息类,当消息队列中为空的时,线程会等待,直到有消息才继续获得继续运行
public class RequestQueue {
private LinkedList queue = new LinkedList();
public synchronized Request getRequest(){
while (queue.size() == 0){
try {
wait();
}catch (InterruptedException e){
}
}
return (Request)queue.remove();
}
public synchronized void addRequest(Request request){
queue.add(request);
notifyAll();
}
}
- RequestQueue:模拟发送消息的类,不断的向消息队列中添加消息
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("线程号:" + Thread.currentThread().getName() + " ID:" + i);
System.out.println("客户端发送请求:" + request);
requestQueue.addRequest(request);
try{
Thread.sleep(10);
}catch (InterruptedException e){
}
//System.out.println("线程名称是:" + Thread.currentThread().getName());
}
System.out.println(Thread.currentThread().getName() + "===================请求结束");
}
}
- ServerThread:模拟服务器处理消息,它并不会马上处理消息,而是将消息放入队列中,让服务器依次处理
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() + "操控" + request);
}
}
}
总结
上面模拟代码是存在问题的,因为消息没处理完,是不会马上给客户端反馈的,所有客户端会处于一个长期等待的状态,体验非常不好,如果这时候客户在不断刷新客户端,更会加重服务器的负担,所以这个时候就需要添加Future模式,及时给客户端一个反馈,待服务器处理完毕,在反馈真实数据给客户端