Guarded Suspension模式

一、定义
guarded是“被保护着的”、“被防卫着的”意思,suspension则是“暂停”的意思。当现在并不适合马上执行某个操作时,就要求想要执行该操作的线程等待,这就是Guarded Suspension Pattern。
Guarded Suspension Pattern 会要求线程等候,以保障实例的安全性,其它类似的称呼还有guarded wait、spin lock等。

二、模式案例
下面的案例是一种简单的消息处理模型,客户端线程发起请求,有请求队列缓存请求,然后发送给服务端线程进行处理。

Request类:

//request类表示请求
public class Request {
    private final String name;
    public Request(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public String toString() {
        return "[ Request " + name + " ]";
    }
}

客户端线程类:

//客户端线程不断生成请求,插入请求队列
public class ClientThread extends Thread {
    private Random random;
    private RequestQueue requestQueue;
    public ClientThread(RequestQueue requestQueue, String name, long seed) {
        super(name);
        this.requestQueue = requestQueue;
        this.random = new Random(seed);
    }
    public void run() {
        for (int i = 0; i < 10000; i++) {
            Request request = new Request("No." + i);
            System.out.println(Thread.currentThread().getName() + " requests " + request);
            requestQueue.putRequest(request);
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
            }
        }
    }
}

服务端线程类:

//客户端线程不断从请求队列中获取请求,然后处理请求
public class ServerThread extends Thread {
    private Random random;
    private RequestQueue requestQueue;
    public ServerThread(RequestQueue requestQueue, String name, long seed) {
        super(name);
        this.requestQueue = requestQueue;
        this.random = new Random(seed);
    }
    public void run() {
        for (int i = 0; i < 10000; i++) {
            Request request = requestQueue.getRequest();
            System.out.println(Thread.currentThread().getName() + " handles  " + request);
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
            }
        }
    }
}

请求队列类:

public class RequestQueue {
    private final LinkedList<Request> queue = new LinkedList<Request>();
    public synchronized Request getRequest() {
        while (queue.size() <= 0) {
            try {                                   
                wait();
            } catch (InterruptedException e) {      
            }                                       
        }                                           
        return (Request)queue.removeFirst();
    }
    public synchronized void putRequest(Request request) {
        queue.addLast(request);
        notifyAll();
    }
}

注:getRequest方法中有一个判断while (queue.size() <= 0),该判断称为Guarded Suspension Pattern 的警戒条件(guard condition)。

执行:

public class Main {
    public static void main(String[] args) {
        RequestQueue requestQueue = new RequestQueue();
        new ClientThread(requestQueue, "Alice", 3141592L).start();
        new ServerThread(requestQueue, "Bobby", 6535897L).start();
    }
}

三、模式讲解
角色:
Guarded Suspension Pattern 的角色如下:

  • GuardedObject (被防卫的对象)参与者
    GuardedObject 参与者是一个拥有被防卫的方法(guardedMethod)的类。当线程执行guardedMethod时,只要满足警戒条件,就能继续执行,否则线程会进入wait set区等待。警戒条件是否成立随着GuardedObject的状态而变化。
    GuardedObject 参与者除了guardedMethod外,可能还有用来更改实例状态的的方法stateChangingMethod。

在Java语言中,是使用while语句和wait方法来实现guardedMethod的;使用notify/notifyAll方法实现stateChangingMethod。如案例中的RequestQueue 类。

注意:Guarded Suspension Pattern 需要使用while,这样可以使从wait set被唤醒的线程在继续向下执行前检查Guard条件。如果改用if,当多个线程被唤醒时,由于wait是继续向下执行的,可能会出现问题。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,099评论 19 139
  • 1.接口和类 I:ExcutorI:ExcutorServiceAC:AbstractExecutorServic...
    BangAiN阅读 2,507评论 0 2
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,804评论 18 399
  • 我是一個典型的90后,想法多的不要不要的,行动却也残疾到不要不要的。 我喜歡写短的文字來表述自己的心情 就像現在 ...
    太阳000阅读 287评论 0 1
  • 作为一个自诩爱好阅读的人,每天有大量的时间使用手机阅读。目前我的信息来源啊主要有以下几方面1、碎片化阅读: PC端...
    下笔有神胡不思阅读 1,090评论 0 5