From 764ff4bf5374e5c09bdd821a82537b2e283c15c3 Mon Sep 17 00:00:00 2001 From: Robert Kasperczyk Date: Fri, 6 Jan 2017 00:57:47 +0100 Subject: [PATCH] Initial commit of guarded suspension design pattern --- guarded-suspension/README.md | 21 ++++++ guarded-suspension/etc/guarded-suspension.png | Bin 0 -> 8011 bytes .../etc/guarded-suspension.ucls | 22 ++++++ .../etc/guarded-suspension.urm.puml | 11 +++ guarded-suspension/pom.xml | 45 ++++++++++++ .../guarded/suspension/GuardedQueue.java | 66 ++++++++++++++++++ .../guarded/suspension/GuardedQueueTest.java | 53 ++++++++++++++ pom.xml | 1 + 8 files changed, 219 insertions(+) create mode 100644 guarded-suspension/README.md create mode 100644 guarded-suspension/etc/guarded-suspension.png create mode 100644 guarded-suspension/etc/guarded-suspension.ucls create mode 100644 guarded-suspension/etc/guarded-suspension.urm.puml create mode 100644 guarded-suspension/pom.xml create mode 100644 guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java create mode 100644 guarded-suspension/src/test/java/com/iluwatar/guarded/suspension/GuardedQueueTest.java diff --git a/guarded-suspension/README.md b/guarded-suspension/README.md new file mode 100644 index 000000000..df10a9ef3 --- /dev/null +++ b/guarded-suspension/README.md @@ -0,0 +1,21 @@ +--- +layout: pattern +title: Guarded Suspension +folder: guarded-suspension +permalink: /patterns/guarded-suspension/ +pumlid: RScv3SCm3030LU819FRPXg5fIm552tnYPFiyjRi3RkbAaYkdoQr5JBy369vrxz7oaSv6XmPhL3e6TCaJ0msU-CAoilTToyG8DdKOw5z0GzcAlvNAN_WZSD1brBHHPmxv0000 +categories: Concurrency +tags: + - Java + - Difficulty-Beginner +--- + +## Intent +Use Guareded suspension pattern to handle a situation when you want to execute a method on object which is not in a proper state. +![Guarded Suspension diagram](./etc/guarded-suspension.png) + +## Applicability +Use Guareded Suspension pattern when: + +* the developer knows that the method execution will be blocked for a finite period of time + diff --git a/guarded-suspension/etc/guarded-suspension.png b/guarded-suspension/etc/guarded-suspension.png new file mode 100644 index 0000000000000000000000000000000000000000..db962e539b40d41364de4496a41d1e6542f8cfff GIT binary patch literal 8011 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 E0VIn*qW}N^ literal 0 HcmV?d00001 diff --git a/guarded-suspension/etc/guarded-suspension.ucls b/guarded-suspension/etc/guarded-suspension.ucls new file mode 100644 index 000000000..2e46325e4 --- /dev/null +++ b/guarded-suspension/etc/guarded-suspension.ucls @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/guarded-suspension/etc/guarded-suspension.urm.puml b/guarded-suspension/etc/guarded-suspension.urm.puml new file mode 100644 index 000000000..f99607d82 --- /dev/null +++ b/guarded-suspension/etc/guarded-suspension.urm.puml @@ -0,0 +1,11 @@ +@startuml +package com.iluwatar.guarded.suspension { + class GuardedQueue { + - LOGGER : Logger {static} + - sourceList : Queue + + GuardedQueue() + + get() : Integer + + put(e : Integer) + } +} +@enduml \ No newline at end of file diff --git a/guarded-suspension/pom.xml b/guarded-suspension/pom.xml new file mode 100644 index 000000000..a7d813ae2 --- /dev/null +++ b/guarded-suspension/pom.xml @@ -0,0 +1,45 @@ + + + + + java-design-patterns + com.iluwatar + 1.14.0-SNAPSHOT + + 4.0.0 + + guarded-suspension + + + junit + junit + + + + + \ No newline at end of file diff --git a/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java b/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java new file mode 100644 index 000000000..a5b16544f --- /dev/null +++ b/guarded-suspension/src/main/java/com/iluwatar/guarded/suspension/GuardedQueue.java @@ -0,0 +1,66 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.guarded.suspension; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; +import java.util.Queue; + + + +public class GuardedQueue { + private static final Logger LOGGER = LoggerFactory.getLogger(GuardedQueue.class); + private Queue 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(); + } + } + + return sourceList.peek(); + } + + /** + * @param e number which we want to put to our queue + */ + public synchronized void put(Integer e) { + sourceList.add(e); + notify(); + LOGGER.info("notifying"); + + } +} diff --git a/guarded-suspension/src/test/java/com/iluwatar/guarded/suspension/GuardedQueueTest.java b/guarded-suspension/src/test/java/com/iluwatar/guarded/suspension/GuardedQueueTest.java new file mode 100644 index 000000000..ca1ffad28 --- /dev/null +++ b/guarded-suspension/src/test/java/com/iluwatar/guarded/suspension/GuardedQueueTest.java @@ -0,0 +1,53 @@ +/** + * The MIT License + * Copyright (c) 2014 Ilkka Seppälä + *

+ * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + *

+ * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.guarded.suspension; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * Created by robertt240 on 1/2/17. + */ +public class GuardedQueueTest { + private volatile Integer value; + + @Test + public void testGet() { + GuardedQueue g = new GuardedQueue(); + ExecutorService executorService = Executors.newFixedThreadPool(2); + executorService.submit(() -> value = g.get()); + executorService.submit(() -> g.put(Integer.valueOf(10))); + executorService.shutdown(); + try { + executorService.awaitTermination(30, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Assert.assertEquals(Integer.valueOf(10), value); + } + +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5ddd3bf98..242ae4b1a 100644 --- a/pom.xml +++ b/pom.xml @@ -134,6 +134,7 @@ event-asynchronous queue-load-leveling object-mother + guarded-suspension