保护性暂挂模式(Guarded Suspension Pattern)

19-04-24 jdon
              

目的

如果要对未处于正确状态的对象执行方法,请使用Guarded Suspension Pattern来处理某种情况。

维基百科说

在并发编程中,guarded suspension是用于管理操作的软件设计模式,其需要获取锁定并且在执行操作之前满足前提条件。Guarded Suspension Pattern通常应用于面向对象程序中的方法调用,并涉及暂停方法调用和调用线程,直到满足前提条件(充当保护)。

源代码

实现基于GuardedQueue,它有两个方法:get和put,条件是我们无法从空队列中获取,因此当线程试图破坏条件时,我们调用Object的wait方法,当其他线程将一个元素放入队列时,它会通知等待者,现在他可以从队列中获取。

类图

第1步:创建GuardedQueue类,它是Guarded Suspension Pattern的实现。

当您想要对未处于正确状态的对象执行方法时,使用Guarded Suspension Pattern来处理这种情况。

public class GuardedQueue {
  private static final Logger LOGGER = LoggerFactory.getLogger(GuardedQueue.class);
  private final Queue<Integer> sourceList;

  public GuardedQueue() {
    this.sourceList = new LinkedList<>();
  }

  /**
   * @return last element of a queue if queue is not empty
   */
  public synchronized Integer get() {
    while (sourceList.isEmpty()) {
      try {
        LOGGER.info("waiting");
        wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    LOGGER.info("getting");
    return sourceList.peek();
  }

  /**
   * @param e number which we want to put to our queue
   */
  public synchronized void put(Integer e) {
    LOGGER.info("putting");
    sourceList.add(e);
    LOGGER.info("notifying");
    notify();
  }
}

第2步:让我们测试一下Guarded Suspension Pattern。

public class App {
  /**
   * Example pattern execution
   *
   * @param args - command line args
   */
  public static void main(String[] args) {
    GuardedQueue guardedQueue = new GuardedQueue();
    ExecutorService executorService = Executors.newFixedThreadPool(3);

    //here we create first thread which is supposed to get from guardedQueue
    executorService.execute(() -> {
          guardedQueue.get();
        }
    );
   
    try {
      Thread.sleep(2000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    executorService.execute(() -> {
          guardedQueue.put(20);
        }
    );
    executorService.shutdown();
    try {
      executorService.awaitTermination(30, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

}

适用性

当开发人员知道方法执行将在有限的时间内被阻止时,使用Guarded Suspension模式。