Guarded Suspension设计模式

什么是Guarded Suspension设计模式

    Suspension是“挂起”、“暂停”的意思,而Guarded则是“担保”的意思,连在一起就是确保挂起。当线程在访问某个对象时,
发现条件不满足,就暂时挂起等待条件满足时再次访问,这一点和Balking设计模式刚好相反(Balking在遇到条件不满足时会放弃)。
    Guarded Suspension设计模式是很多设计模式的基础,比如生产者消费者模式,Worker Thread设计模式,等等,同样在Java
并发包中的BlockingQueue中也大量使用到了Guarded Suspension设计模式

Guarded Suspension的示例

package MutilThreadModel.GuardedSuspensionModel;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

/**
 * Created by JYM on 2019/1/10
 * Guarded Suspension设计模式
 * */

public class GuardedSuspensionQueue
{
    //定义存放Integer类型的queue
    private  final LinkedList<Integer> queue = new LinkedList<>();

    //定义queue的最大容量为100
    private final int LIMIT = 100;

    //往queue中插入数据,如果queue中的元素超过了最大容量,则会陷入阻塞
    public void offer(Integer data) throws InterruptedException
    {
        synchronized (this)
        {
            //判断queue的当前元素是否超过了LIMIT
            while (queue.size() >= LIMIT)
            {
                //挂起当前线程,使其陷入阻塞
                System.out.println("queue中的元素个数超过了LIMIT,当前线程被挂起,使其陷入阻塞状态!");
                this.wait();
            }
            //插入元素并且唤醒take线程
            queue.addLast(data);
            this.notifyAll();
        }
    }

    //从队列中获取元素,如果队列此时为空,则会使当前线程阻塞
    public Integer take() throws InterruptedException
    {
        synchronized (this)
        {
            //判断如果队列为空
            while (queue.isEmpty())
            {
                //则挂起当前线程
                System.out.println("queue中的元素个数为0,当前线程被挂起!");
                this.wait();
            }
            //通知offer线程可以继续插入数据了
            this.notifyAll();
            return queue.removeFirst();
        }
    }

    //简单测试
    public static void main(String[] args)
    {
        GuardedSuspensionQueue guardedSuspensionQueue = new GuardedSuspensionQueue();

        //创建10个生产线程
        for (int i=0;i<10;i++)
        {
            new Thread(()->
            {
                try{
                    for (int j=1;j<15;j++)
                    {
                        guardedSuspensionQueue.offer(j);
                    }
                }catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                slowly();
            },"第"+(i+1)+"个生产线程").start();
        }

        //创建2个消费线程
        for (int i=0;i<10;i++)
        {
            new Thread(()->
            {
                int result;
                try{
                    while (guardedSuspensionQueue.take() != null)
                    {
                        result=guardedSuspensionQueue.take();
                        System.out.println("取出队列中的第一个数据:"+result);
                    }
                }catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                slowly();
            },"第"+(i+1)+"个消费线程").start();
        }
    }

    //暂时休眠
    private static void slowly()
    {
        try{
            TimeUnit.MILLISECONDS.sleep(1);
        }catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

/**
 * 在GuardedSuspensionQueue中,我们需要保证线程安全的是queue,分别在take和offer方法中对应的临界值是queue为空和queue的数量>=100,当Queue中的
 * 数据已经满时,如果有线程调用offer方法则会挂起(Suspension),同样,当queue没有数据的时候,调用take方法也会被挂起。
 * Guarded Suspension模式是一个非常基础的设计模式,它主要关注的是当某个条件(临界值)不满足时将操作的线程正确地挂起,
 * 以防止出现数据不一致或者操作超过临界值的控制范围。
 * */

总结:

Guarded Suspension设计模式并不复杂,但是它是很多其他线程设计模式的基础,比如生产者消费者模式,后文中的Thread Worker设计模式、Balking设计模式等,都可以看到Guarded Suspension模式的影子,Guarded Suspension的关注点在于临界值的条件是否满足,当达到设置的临界值时相关线程则会被挂起。

猜你喜欢

转载自blog.csdn.net/leying521/article/details/86303729