资讯专栏INFORMATION COLUMN

Java多线程基础(五)——Guarded Suspension模式

golden_hamster / 3027人阅读

摘要:会要求线程等候,以保障实例的安全性,其它类似的称呼还有等。警戒条件是否成立随着的状态而变化。注意需要使用,这样可以使从被唤醒的线程在继续向下执行前检查条件。

一、定义

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 queue = new LinkedList();
    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是继续向下执行的,可能会出现问题。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71486.html

相关文章

  • Java线程基础(六)——Balking模式

    摘要:二模式案例该案例会保存数据的属性,之前所保存的属性都会被覆盖。当线程执行时,只有满足警戒条件时,才会继续执行,否则会立即返回。警戒条件的成立与否,会随着参与者的状态而变化。注上述示例中,类就是被警戒的对象参与者,方法是,方法是。 一、定义 Balking是退缩不前的意思。Balking Pattern和Guarded Suspension Pattern 一样需要警戒条件。在Balk...

    Faremax 评论0 收藏0
  • Java线程进阶()—— J.U.C之locks框架:LockSupport

    摘要:初始时,为,当调用方法时,线程的加,当调用方法时,如果为,则调用线程进入阻塞状态。该对象一般供监视诊断工具确定线程受阻塞的原因时使用。 showImg(https://segmentfault.com/img/remote/1460000016012503); 本文首发于一世流云的专栏:https://segmentfault.com/blog... 一、LockSupport类简介...

    jsyzchen 评论0 收藏0
  • Java线程进阶(二)—— J.U.C之locks框架:接口

    摘要:二接口简介可以看做是类的方法的替代品,与配合使用。当线程执行对象的方法时,当前线程会立即释放锁,并进入对象的等待区,等待其它线程唤醒或中断。 showImg(https://segmentfault.com/img/remote/1460000016012601); 本文首发于一世流云的专栏:https://segmentfault.com/blog... 本系列文章中所说的juc-...

    dkzwm 评论0 收藏0
  • 并发基础

    摘要:关于,这个方法只会唤醒一个线程,并且不允许指定唤醒哪个线程,这是可能会发生死锁的。使用不可变对象降低了垃圾回收所产生的额外开销,同时也可以减少一些为了维护在并发中的的代码开销。 前言 跟着 The Java Tutorials 把并发的一些基础过了一遍,发现仍然还是有很多不清楚的地方,主要是因为平常没有机会实际应用吧,理论知识要有,实践也很重要,哪怕是写些小 demo 也可以的。 虽然...

    Warren 评论0 收藏0
  • Java™ 教程(态性)

    多态性 多态性的字典定义是指生物学中的原理,其中生物体或物种可以具有许多不同的形式或阶段,这个原则也可以应用于面向对象的编程和像Java语言之类的语言,类的子类可以定义它们自己的唯一行为,但仍然共享父类的一些相同功能。 可以通过对Bicycle类的微小修改来演示多态性,例如,可以将printDescription方法添加到显示当前存储在实例中的所有数据的类中。 public void printD...

    J4ck_Chan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<