From 3ed3bc1fa52b7c1ce9a5684ce08ac03073e7668b Mon Sep 17 00:00:00 2001 From: gwildor28 <jbenedetti28@hotmail.com> Date: Mon, 7 Mar 2016 19:40:50 +0000 Subject: [PATCH 1/8] Added mutex and semaphore modules to demonstrate locks Added two modules to demonstrate locks. Mutex demonstrates a simple mutual exclusion lock. Semaphore demonstrates a semaphore for controlling access to a pool of resources. The main class of both programs is App.java. --- mutex/pom.xml | 35 ++++++ .../src/main/java/com/iluwatar/mutex/App.java | 42 +++++++ .../src/main/java/com/iluwatar/mutex/Jar.java | 58 ++++++++++ .../main/java/com/iluwatar/mutex/Lock.java | 34 ++++++ .../main/java/com/iluwatar/mutex/Mutex.java | 46 ++++++++ .../main/java/com/iluwatar/mutex/Thief.java | 51 +++++++++ pom.xml | 2 + semaphore/pom.xml | 35 ++++++ .../main/java/com/iluwatar/semaphore/App.java | 43 ++++++++ .../java/com/iluwatar/semaphore/Customer.java | 63 +++++++++++ .../java/com/iluwatar/semaphore/Fruit.java | 60 ++++++++++ .../com/iluwatar/semaphore/FruitBowl.java | 78 +++++++++++++ .../com/iluwatar/semaphore/FruitShop.java | 103 ++++++++++++++++++ .../java/com/iluwatar/semaphore/Lock.java | 34 ++++++ .../com/iluwatar/semaphore/Semaphore.java | 51 +++++++++ 15 files changed, 735 insertions(+) create mode 100644 mutex/pom.xml create mode 100644 mutex/src/main/java/com/iluwatar/mutex/App.java create mode 100644 mutex/src/main/java/com/iluwatar/mutex/Jar.java create mode 100644 mutex/src/main/java/com/iluwatar/mutex/Lock.java create mode 100644 mutex/src/main/java/com/iluwatar/mutex/Mutex.java create mode 100644 mutex/src/main/java/com/iluwatar/mutex/Thief.java create mode 100644 semaphore/pom.xml create mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/App.java create mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/Customer.java create mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java create mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java create mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java create mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/Lock.java create mode 100644 semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java diff --git a/mutex/pom.xml b/mutex/pom.xml new file mode 100644 index 000000000..5b7058083 --- /dev/null +++ b/mutex/pom.xml @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<!-- + + 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. + +--> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.iluwatar</groupId> + <artifactId>java-design-patterns</artifactId> + <version>1.11.0-SNAPSHOT</version> + </parent> + <artifactId>mutex</artifactId> +</project> diff --git a/mutex/src/main/java/com/iluwatar/mutex/App.java b/mutex/src/main/java/com/iluwatar/mutex/App.java new file mode 100644 index 000000000..e2d10763f --- /dev/null +++ b/mutex/src/main/java/com/iluwatar/mutex/App.java @@ -0,0 +1,42 @@ +/** + * 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.mutex; + +/** + * App. + */ +public class App { + + /** + * main method + */ + public static void main(String[] args) { + Mutex mutex = new Mutex(); + Jar jar = new Jar(mutex); + Thief peter = new Thief("Peter", jar); + Thief john = new Thief("John", jar); + peter.start(); + john.start(); + } + +} diff --git a/mutex/src/main/java/com/iluwatar/mutex/Jar.java b/mutex/src/main/java/com/iluwatar/mutex/Jar.java new file mode 100644 index 000000000..6cbe009d8 --- /dev/null +++ b/mutex/src/main/java/com/iluwatar/mutex/Jar.java @@ -0,0 +1,58 @@ +/** + * 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.mutex; + +/** + * Jar. + */ +public class Jar { + + private Lock lock; + + private int beans = 1000; + + public Jar(Lock lock) { + this.lock = lock; + } + + /** + * takeBean method + */ + public boolean takeBean(Thief thief) { + boolean success = false; + try { + lock.acquire(); + success = beans > 0; + if (success) { + beans = beans - 1; + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + lock.release(); + } + + return success; + } + +} diff --git a/mutex/src/main/java/com/iluwatar/mutex/Lock.java b/mutex/src/main/java/com/iluwatar/mutex/Lock.java new file mode 100644 index 000000000..b748f3761 --- /dev/null +++ b/mutex/src/main/java/com/iluwatar/mutex/Lock.java @@ -0,0 +1,34 @@ +/** + * 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.mutex; + +/** + * Lock. + */ +public interface Lock { + + void acquire() throws InterruptedException; + + void release(); + +} diff --git a/mutex/src/main/java/com/iluwatar/mutex/Mutex.java b/mutex/src/main/java/com/iluwatar/mutex/Mutex.java new file mode 100644 index 000000000..a8cf6a919 --- /dev/null +++ b/mutex/src/main/java/com/iluwatar/mutex/Mutex.java @@ -0,0 +1,46 @@ +/** + * 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.mutex; + +/** + * Mutex. + */ +public class Mutex implements Lock { + private Object owner = null; + + @Override + public synchronized void acquire() throws InterruptedException { + while (owner != null) { + wait(); + } + + owner = Thread.currentThread(); + } + + @Override + public synchronized void release() { + owner = null; + notify(); + } + +} diff --git a/mutex/src/main/java/com/iluwatar/mutex/Thief.java b/mutex/src/main/java/com/iluwatar/mutex/Thief.java new file mode 100644 index 000000000..8fbc75f92 --- /dev/null +++ b/mutex/src/main/java/com/iluwatar/mutex/Thief.java @@ -0,0 +1,51 @@ +/** + * 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.mutex; + +/** + * Thief. + */ +public class Thief extends Thread { + + private String name; + + private Jar jar; + + public Thief(String name, Jar jar) { + this.name = name; + this.jar = jar; + } + + @Override + public void run() { + int beans = 0; + + while (jar.takeBean(this)) { + beans = beans + 1; + System.out.println(name + " took a bean."); + } + + System.out.println(name + " took " + beans + " beans."); + } + +} diff --git a/pom.xml b/pom.xml index 555844660..fa0fe771c 100644 --- a/pom.xml +++ b/pom.xml @@ -123,6 +123,8 @@ <module>feature-toggle</module> <module>value-object</module> <module>monad</module> + <module>mutex</module> + <module>semaphore</module> </modules> <dependencyManagement> diff --git a/semaphore/pom.xml b/semaphore/pom.xml new file mode 100644 index 000000000..66a961c3f --- /dev/null +++ b/semaphore/pom.xml @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<!-- + + 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. + +--> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.iluwatar</groupId> + <artifactId>java-design-patterns</artifactId> + <version>1.11.0-SNAPSHOT</version> + </parent> + <artifactId>semaphore</artifactId> +</project> diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/App.java b/semaphore/src/main/java/com/iluwatar/semaphore/App.java new file mode 100644 index 000000000..4dd5a764a --- /dev/null +++ b/semaphore/src/main/java/com/iluwatar/semaphore/App.java @@ -0,0 +1,43 @@ +/** + * 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.semaphore; + +/** + * App. + */ +public class App { + + /** + * main method + */ + public static void main(String[] args) { + FruitShop shop = new FruitShop(); + new Customer("Peter", shop).start(); + new Customer("Paul", shop).start(); + new Customer("Mary", shop).start(); + new Customer("John", shop).start(); + new Customer("Ringo", shop).start(); + new Customer("George", shop).start(); + } + +} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java b/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java new file mode 100644 index 000000000..a3fc65ac3 --- /dev/null +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java @@ -0,0 +1,63 @@ +/** + * 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.semaphore; + +/** + * Customer. + */ +public class Customer extends Thread { + + private String name; + private FruitShop fruitShop; + private FruitBowl fruitBowl; + + /** + * Customer constructor + */ + public Customer(String name, FruitShop fruitShop) { + this.name = name; + this.fruitShop = fruitShop; + this.fruitBowl = new FruitBowl(); + } + + /** + * run method + */ + public void run() { + + while (fruitShop.countFruit() > 0) { + FruitBowl bowl = fruitShop.takeBowl(); + Fruit fruit; + + if (bowl != null && (fruit = bowl.take()) != null) { + System.out.println(name + " took an " + fruit); + fruitBowl.put(fruit); + fruitShop.returnBowl(bowl); + } + } + + System.out.println(name + " took " + fruitBowl); + + } + +} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java b/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java new file mode 100644 index 000000000..ecf8d1d29 --- /dev/null +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java @@ -0,0 +1,60 @@ +/** + * 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.semaphore; + +/** + * Fruit. + */ +public class Fruit { + + public static enum FruitType { + ORANGE, APPLE, LEMON + } + + private FruitType type; + + public Fruit(FruitType type) { + this.type = type; + } + + public FruitType getType() { + return type; + } + + /** + * toString method + */ + public String toString() { + switch (type) { + case ORANGE: + return "Orange"; + case APPLE: + return "Apple"; + case LEMON: + return "Lemon"; + default: + return ""; + } + } + +} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java b/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java new file mode 100644 index 000000000..7760b8e3a --- /dev/null +++ b/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java @@ -0,0 +1,78 @@ +/** + * 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.semaphore; + +import java.util.ArrayList; + +/** + * FruitBowl. + */ +public class FruitBowl { + + private ArrayList<Fruit> fruit = new ArrayList<>(); + + public int countFruit() { + return fruit.size(); + } + + public void put(Fruit f) { + fruit.add(f); + } + + /** + * take method + */ + public Fruit take() { + if (fruit.isEmpty()) { + return null; + } else { + return fruit.remove(0); + } + } + + /** + * toString method + */ + public String toString() { + int apples = 0; + int oranges = 0; + int lemons = 0; + + for (Fruit f : fruit) { + switch (f.getType()) { + case APPLE: + apples++; + break; + case ORANGE: + oranges++; + break; + case LEMON: + lemons++; + break; + default: + } + } + + return apples + " Apples, " + oranges + " Oranges, and " + lemons + " Lemons"; + } +} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java b/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java new file mode 100644 index 000000000..fff764bad --- /dev/null +++ b/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java @@ -0,0 +1,103 @@ +/** + * 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.semaphore; + +/** + * FruitShop. + */ +public class FruitShop { + + private FruitBowl[] bowls = { + new FruitBowl(), + new FruitBowl(), + new FruitBowl() + }; + + private boolean[] available = { + true, + true, + true + }; + + private Semaphore semaphore; + + /** + * FruitShop constructor + */ + public FruitShop() { + for (int i = 0; i < 100; i++) { + bowls[0].put(new Fruit(Fruit.FruitType.APPLE)); + bowls[1].put(new Fruit(Fruit.FruitType.ORANGE)); + bowls[2].put(new Fruit(Fruit.FruitType.LEMON)); + } + + semaphore = new Semaphore(3); + } + + public synchronized int countFruit() { + return bowls[0].countFruit() + bowls[1].countFruit() + bowls[2].countFruit(); + } + + /** + * takeBowl method + */ + public synchronized FruitBowl takeBowl() { + + FruitBowl bowl = null; + + try { + semaphore.acquire(); + + if (available[0]) { + bowl = bowls[0]; + available[0] = false; + } else if (available[1]) { + bowl = bowls[1]; + available[1] = false; + } else if (available[2]) { + bowl = bowls[2]; + available[2] = false; + } + + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + semaphore.release(); + } + return bowl; + } + + /** + * returnBowl method + */ + public synchronized void returnBowl(FruitBowl bowl) { + if (bowl == bowls[0]) { + available[0] = true; + } else if (bowl == bowls[1]) { + available[1] = true; + } else if (bowl == bowls[2]) { + available [2] = true; + } + } + +} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java b/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java new file mode 100644 index 000000000..99b8f85b5 --- /dev/null +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java @@ -0,0 +1,34 @@ +/** + * 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.semaphore; + +/** + * Lock. + */ +public interface Lock { + + void acquire() throws InterruptedException; + + void release(); + +} diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java b/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java new file mode 100644 index 000000000..5873df2b5 --- /dev/null +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java @@ -0,0 +1,51 @@ +/** + * 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.semaphore; + +/** + * Semaphore. + */ +public class Semaphore implements Lock { + + private int counter; + + public Semaphore(int counter) { + this.counter = counter; + } + + /** + * acquire method + */ + public synchronized void acquire() throws InterruptedException { + while (counter == 0) { + wait(); + } + counter = counter - 1; + } + + public synchronized void release() { + counter = counter + 1; + notify(); + } + +} From 6e4b2699398231f47b0bcf75b22336d4d470fd27 Mon Sep 17 00:00:00 2001 From: gwildor28 <jbenedetti28@hotmail.com> Date: Thu, 24 Mar 2016 18:13:37 +0000 Subject: [PATCH 2/8] Update according to review comments #397 - Added descriptions - Added junit tests - Added javadoc - Added index.md - Added class diagrams --- mutex/etc/mutex.png | Bin 0 -> 12737 bytes mutex/index.md | 30 ++++++++++++++++ mutex/pom.xml | 9 ++++- .../src/main/java/com/iluwatar/mutex/App.java | 10 +++++- .../src/main/java/com/iluwatar/mutex/Jar.java | 14 ++++++-- .../main/java/com/iluwatar/mutex/Lock.java | 2 +- .../main/java/com/iluwatar/mutex/Mutex.java | 16 +++++++-- .../main/java/com/iluwatar/mutex/Thief.java | 19 +++++++--- .../test/java/com/iluwatar/mutex/AppTest.java | 34 ++++++++++++++++++ semaphore/etc/semaphore.png | Bin 0 -> 30089 bytes semaphore/index.md | 33 +++++++++++++++++ semaphore/pom.xml | 9 ++++- .../main/java/com/iluwatar/semaphore/App.java | 9 ++++- .../java/com/iluwatar/semaphore/Customer.java | 25 +++++++++---- .../java/com/iluwatar/semaphore/Fruit.java | 2 +- .../com/iluwatar/semaphore/FruitBowl.java | 16 +++++++-- .../com/iluwatar/semaphore/FruitShop.java | 31 ++++++++++++---- .../java/com/iluwatar/semaphore/Lock.java | 2 +- .../com/iluwatar/semaphore/Semaphore.java | 12 +++++-- .../java/com/iluwatar/semaphore/AppTest.java | 34 ++++++++++++++++++ 20 files changed, 273 insertions(+), 34 deletions(-) create mode 100644 mutex/etc/mutex.png create mode 100644 mutex/index.md create mode 100644 mutex/src/test/java/com/iluwatar/mutex/AppTest.java create mode 100644 semaphore/etc/semaphore.png create mode 100644 semaphore/index.md create mode 100644 semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java diff --git a/mutex/etc/mutex.png b/mutex/etc/mutex.png new file mode 100644 index 0000000000000000000000000000000000000000..3b7c966f87dffab72c65a77c2578c801086f7d9e GIT binary patch literal 12737 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	VGkgbka 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 RF7OUbSwT&{Qq~OqKL9K>lx6?` literal 0 HcmV?d00001 diff --git a/mutex/index.md b/mutex/index.md new file mode 100644 index 000000000..24edad7eb --- /dev/null +++ b/mutex/index.md @@ -0,0 +1,30 @@ +--- +layout: pattern +title: Mutex +folder: mutex +permalink: /patterns/mutex/ +categories: Lock +tags: + - Java + - Difficulty-Beginner +--- + +## Also known as +Mutual Exclusion Lock +Binary Semaphore + +## Intent +Create a lock which only allows a single thread to access a resource at any one instant. + + + +## Applicability +Use a Mutex when + +* you need to prevent two threads accessing a critical section at the same time +* concurrent access to a resource could lead to a race condition + +## Credits + +* [Lock (computer science)] (http://en.wikipedia.org/wiki/Lock_(computer_science)) +* [Semaphores] (http://tutorials.jenkov.com/java-concurrency/semaphores.html) diff --git a/mutex/pom.xml b/mutex/pom.xml index 5b7058083..07c2d793c 100644 --- a/mutex/pom.xml +++ b/mutex/pom.xml @@ -2,7 +2,7 @@ <!-- The MIT License - Copyright (c) 2014 Ilkka Sepp�l� + 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 @@ -32,4 +32,11 @@ <version>1.11.0-SNAPSHOT</version> </parent> <artifactId>mutex</artifactId> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> </project> diff --git a/mutex/src/main/java/com/iluwatar/mutex/App.java b/mutex/src/main/java/com/iluwatar/mutex/App.java index e2d10763f..559453500 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/App.java +++ b/mutex/src/main/java/com/iluwatar/mutex/App.java @@ -23,7 +23,15 @@ package com.iluwatar.mutex; /** - * App. + * A Mutex prevents multiple threads from accessing a resource simultaneously. + * <p> + * In this example we have two thieves who are taking beans from a jar. + * Only one thief can take a bean at a time. This is ensured by a Mutex lock + * which must be acquired in order to access the jar. Each thief attempts to + * acquire the lock, take a bean and then release the lock. If the lock has + * already been acquired, the thief will be prevented from continuing (blocked) + * until the lock has been released. The thieves stop taking beans once there + * are no beans left to take. */ public class App { diff --git a/mutex/src/main/java/com/iluwatar/mutex/Jar.java b/mutex/src/main/java/com/iluwatar/mutex/Jar.java index 6cbe009d8..e049b7a75 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Jar.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Jar.java @@ -23,12 +23,20 @@ package com.iluwatar.mutex; /** - * Jar. + * A Jar has a resource of beans which can only be accessed by a single Thief + * (thread) at any one time. A Mutex lock is used to prevent more than one Thief + * taking a bean simultaneously. */ public class Jar { - private Lock lock; + /** + * The lock which must be acquired to access the beans resource. + */ + private final Lock lock; + /** + * The resource within the jar. + */ private int beans = 1000; public Jar(Lock lock) { @@ -36,7 +44,7 @@ public class Jar { } /** - * takeBean method + * Method for a thief to take a bean. */ public boolean takeBean(Thief thief) { boolean success = false; diff --git a/mutex/src/main/java/com/iluwatar/mutex/Lock.java b/mutex/src/main/java/com/iluwatar/mutex/Lock.java index b748f3761..fef67010e 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Lock.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Lock.java @@ -23,7 +23,7 @@ package com.iluwatar.mutex; /** - * Lock. + * Lock is an interface for a lock which can be acquired and released. */ public interface Lock { diff --git a/mutex/src/main/java/com/iluwatar/mutex/Mutex.java b/mutex/src/main/java/com/iluwatar/mutex/Mutex.java index a8cf6a919..e15deaf48 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Mutex.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Mutex.java @@ -23,11 +23,20 @@ package com.iluwatar.mutex; /** - * Mutex. + * Mutex is an implementation of a mutual exclusion lock. */ public class Mutex implements Lock { - private Object owner = null; + /** + * The current owner of the lock. + */ + private Object owner; + + /** + * Method called by a thread to acquire the lock. If the lock has already + * been acquired this will wait until the lock has been released to + * re-attempt the acquire. + */ @Override public synchronized void acquire() throws InterruptedException { while (owner != null) { @@ -37,6 +46,9 @@ public class Mutex implements Lock { owner = Thread.currentThread(); } + /** + * Method called by a thread to release the lock. + */ @Override public synchronized void release() { owner = null; diff --git a/mutex/src/main/java/com/iluwatar/mutex/Thief.java b/mutex/src/main/java/com/iluwatar/mutex/Thief.java index 8fbc75f92..58ce019e0 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Thief.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Thief.java @@ -23,19 +23,30 @@ package com.iluwatar.mutex; /** - * Thief. + * Thief is a class which continually tries to acquire a jar and take a bean + * from it. When the jar is empty the thief stops. */ public class Thief extends Thread { - private String name; - - private Jar jar; + /** + * The name of the thief. + */ + private final String name; + + /** + * The jar + */ + private final Jar jar; public Thief(String name, Jar jar) { this.name = name; this.jar = jar; } + /** + * In the run method the thief repeatedly tries to take a bean until none + * are left. + */ @Override public void run() { int beans = 0; diff --git a/mutex/src/test/java/com/iluwatar/mutex/AppTest.java b/mutex/src/test/java/com/iluwatar/mutex/AppTest.java new file mode 100644 index 000000000..f3a123519 --- /dev/null +++ b/mutex/src/test/java/com/iluwatar/mutex/AppTest.java @@ -0,0 +1,34 @@ +/** + * 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.mutex; + +import org.junit.Test; +import java.io.IOException; + +public class AppTest{ + @Test + public void test() throws IOException { + String[] args = {}; + App.main(args); + } +} \ No newline at end of file diff --git a/semaphore/etc/semaphore.png b/semaphore/etc/semaphore.png new file mode 100644 index 0000000000000000000000000000000000000000..a2ff6d0c4f5bb931d724a4dd3872e7dde4730102 GIT binary patch literal 30089 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 literal 0 HcmV?d00001 diff --git a/semaphore/index.md b/semaphore/index.md new file mode 100644 index 000000000..e3e215d5a --- /dev/null +++ b/semaphore/index.md @@ -0,0 +1,33 @@ +--- +layout: pattern +title: Semaphore +folder: semaphore +permalink: /patterns/semaphore/ +categories: Lock +tags: + - Java + - Difficulty-Beginner +--- + +## Also known as +Counting Semaphore + +## Intent +Create a lock which mediates access to a pool of resources. +Only a limited number of threads, specified at the creation +of the semaphore, can access the resources at any given time. +A semaphore which only allows one concurrent access to a resource +is called a binary semaphore. + + + +## Applicability +Use a Semaphore when + +* you have a pool of resources to allocate to different threads +* concurrent access to a resource could lead to a race condition + +## Credits + +* [Semaphore(programming)] (http://en.wikipedia.org/wiki/Semaphore_(programming)) +* [Semaphores] (http://tutorials.jenkov.com/java-concurrency/semaphores.html) diff --git a/semaphore/pom.xml b/semaphore/pom.xml index 66a961c3f..14b551a1a 100644 --- a/semaphore/pom.xml +++ b/semaphore/pom.xml @@ -2,7 +2,7 @@ <!-- The MIT License - Copyright (c) 2014 Ilkka Sepp�l� + 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 @@ -32,4 +32,11 @@ <version>1.11.0-SNAPSHOT</version> </parent> <artifactId>semaphore</artifactId> + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> </project> diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/App.java b/semaphore/src/main/java/com/iluwatar/semaphore/App.java index 4dd5a764a..272de37b0 100644 --- a/semaphore/src/main/java/com/iluwatar/semaphore/App.java +++ b/semaphore/src/main/java/com/iluwatar/semaphore/App.java @@ -23,7 +23,14 @@ package com.iluwatar.semaphore; /** - * App. + * A Semaphore mediates access by a group of threads to a pool of resources. + * <p> + * In this example a group of customers are taking fruit from a fruit shop. + * There is a bowl each of apples, oranges and lemons. Only one customer can + * access a bowl simultaneously. A Semaphore is used to indicate how many + * resources are currently available and must be acquired in order for a bowl + * to be given to a customer. Customers continually try to take fruit until + * there is no fruit left in the shop. */ public class App { diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java b/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java index a3fc65ac3..0a4713438 100644 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Customer.java @@ -23,13 +23,25 @@ package com.iluwatar.semaphore; /** - * Customer. + * A Customer attempts to repeatedly take Fruit from the FruitShop by + * taking Fruit from FruitBowl instances. */ public class Customer extends Thread { - - private String name; - private FruitShop fruitShop; - private FruitBowl fruitBowl; + + /** + * Name of the Customer. + */ + private final String name; + + /** + * The FruitShop he is using. + */ + private final FruitShop fruitShop; + + /** + * Their bowl of Fruit. + */ + private final FruitBowl fruitBowl; /** * Customer constructor @@ -41,7 +53,8 @@ public class Customer extends Thread { } /** - * run method + * The Customer repeatedly takes Fruit from the FruitShop until no Fruit + * remains. */ public void run() { diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java b/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java index ecf8d1d29..0a4224d20 100644 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Fruit.java @@ -23,7 +23,7 @@ package com.iluwatar.semaphore; /** - * Fruit. + * Fruit is a resource stored in a FruitBowl. */ public class Fruit { diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java b/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java index 7760b8e3a..ac2b87ada 100644 --- a/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java +++ b/semaphore/src/main/java/com/iluwatar/semaphore/FruitBowl.java @@ -25,23 +25,33 @@ package com.iluwatar.semaphore; import java.util.ArrayList; /** - * FruitBowl. + * A FruitBowl contains Fruit. */ public class FruitBowl { private ArrayList<Fruit> fruit = new ArrayList<>(); + /** + * + * @return The amount of Fruit left in the bowl. + */ public int countFruit() { return fruit.size(); } + /** + * Put an item of Fruit into the bowl. + * + * @param f fruit + */ public void put(Fruit f) { fruit.add(f); } /** - * take method - */ + * Take an item of Fruit out of the bowl. + * @return The Fruit taken out of the bowl, or null if empty. + */ public Fruit take() { if (fruit.isEmpty()) { return null; diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java b/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java index fff764bad..315b46986 100644 --- a/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java +++ b/semaphore/src/main/java/com/iluwatar/semaphore/FruitShop.java @@ -23,22 +23,31 @@ package com.iluwatar.semaphore; /** - * FruitShop. + * A FruitShop contains three FruitBowl instances and controls access to them. */ public class FruitShop { - + + /** + * The FruitBowl instances stored in the class. + */ private FruitBowl[] bowls = { new FruitBowl(), new FruitBowl(), new FruitBowl() }; - + + /** + * Access flags for each of the FruitBowl instances. + */ private boolean[] available = { true, true, true }; - + + /** + * The Semaphore that controls access to the class resources. + */ private Semaphore semaphore; /** @@ -53,13 +62,19 @@ public class FruitShop { semaphore = new Semaphore(3); } - + + /** + * + * @return The amount of Fruit left in the shop. + */ public synchronized int countFruit() { return bowls[0].countFruit() + bowls[1].countFruit() + bowls[2].countFruit(); } /** - * takeBowl method + * Method called by Customer to get a FruitBowl from the shop. This method + * will try to acquire the Semaphore before returning the first available + * FruitBowl. */ public synchronized FruitBowl takeBowl() { @@ -88,7 +103,9 @@ public class FruitShop { } /** - * returnBowl method + * Method called by a Customer instance to return a FruitBowl to the shop. + * This method releases the Semaphore, making the FruitBowl available to + * another Customer. */ public synchronized void returnBowl(FruitBowl bowl) { if (bowl == bowls[0]) { diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java b/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java index 99b8f85b5..4b651685c 100644 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Lock.java @@ -23,7 +23,7 @@ package com.iluwatar.semaphore; /** - * Lock. + * Lock is an interface for a lock which can be acquired and released. */ public interface Lock { diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java b/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java index 5873df2b5..79f3b4465 100644 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java @@ -23,10 +23,13 @@ package com.iluwatar.semaphore; /** - * Semaphore. + * Semaphore is an implementation of a semaphore lock. */ public class Semaphore implements Lock { + /** + * The number of concurrent resource accesses which are allowed. + */ private int counter; public Semaphore(int counter) { @@ -34,7 +37,9 @@ public class Semaphore implements Lock { } /** - * acquire method + * Method called by a thread to acquire the lock. If there are no resources + * available this will wait until the lock has been released to re-attempt + * the acquire. */ public synchronized void acquire() throws InterruptedException { while (counter == 0) { @@ -43,6 +48,9 @@ public class Semaphore implements Lock { counter = counter - 1; } + /** + * Method called by a thread to release the lock. + */ public synchronized void release() { counter = counter + 1; notify(); diff --git a/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java b/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java new file mode 100644 index 000000000..4b286588d --- /dev/null +++ b/semaphore/src/test/java/com/iluwatar/semaphore/AppTest.java @@ -0,0 +1,34 @@ +/** + * 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.semaphore; + +import org.junit.Test; +import java.io.IOException; + +public class AppTest{ + @Test + public void test() throws IOException { + String[] args = {}; + App.main(args); + } +} \ No newline at end of file From e2af78f417c076243cf8202b61a651485aac13b9 Mon Sep 17 00:00:00 2001 From: gwildor28 <jbenedetti28@hotmail.com> Date: Tue, 29 Mar 2016 13:42:54 +0100 Subject: [PATCH 3/8] Update According to Review Comments #397 Resubmit of updates --- mutex/{index.md => README.md} | 0 semaphore/{index.md => README.md} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename mutex/{index.md => README.md} (100%) rename semaphore/{index.md => README.md} (100%) diff --git a/mutex/index.md b/mutex/README.md similarity index 100% rename from mutex/index.md rename to mutex/README.md diff --git a/semaphore/index.md b/semaphore/README.md similarity index 100% rename from semaphore/index.md rename to semaphore/README.md From 3f9a7566573473235947099b8a68d892f6aeed3f Mon Sep 17 00:00:00 2001 From: gwildor28 <jbenedetti28@hotmail.com> Date: Wed, 13 Apr 2016 19:25:02 +0100 Subject: [PATCH 4/8] pom update --- pom.xml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index 20b468246..98b79de08 100644 --- a/pom.xml +++ b/pom.xml @@ -1,19 +1,15 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - 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 @@ -21,7 +17,6 @@ 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. - --> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> @@ -50,6 +45,7 @@ <guava.version>19.0</guava.version> <systemrules.version>1.15.1</systemrules.version> <mockito.version>1.10.19</mockito.version> + <hierarchical-junit-runner-version>4.12.1</hierarchical-junit-runner-version> </properties> <modules> <module>abstract-factory</module> @@ -123,8 +119,7 @@ <module>feature-toggle</module> <module>value-object</module> <module>monad</module> - <module>mutex</module> - <module>semaphore</module> + <module>mute-idiom</module> </modules> <dependencyManagement> @@ -197,6 +192,12 @@ <version>${systemrules.version}</version> <scope>test</scope> </dependency> + <dependency> + <groupId>de.bechte.junit</groupId> + <artifactId>junit-hierarchicalcontextrunner</artifactId> + <version>${hierarchical-junit-runner-version}</version> + <scope>test</scope> + </dependency> </dependencies> </dependencyManagement> @@ -396,4 +397,4 @@ </plugins> </reporting> -</project> +</project> \ No newline at end of file From ca8be7c43e3bc5a1590c5352137dcb2e203855b5 Mon Sep 17 00:00:00 2001 From: gwildor28 <jbenedetti28@hotmail.com> Date: Wed, 13 Apr 2016 19:26:31 +0100 Subject: [PATCH 5/8] pom update --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index 98b79de08..9d66f5f9b 100644 --- a/pom.xml +++ b/pom.xml @@ -120,6 +120,8 @@ <module>value-object</module> <module>monad</module> <module>mute-idiom</module> + <module>mutex</module> + <module>semaphore</module> </modules> <dependencyManagement> From 685d093cff803609c25d35e58bf663c55262c2fa Mon Sep 17 00:00:00 2001 From: gwildor28 <jbenedetti28@hotmail.com> Date: Thu, 14 Apr 2016 17:33:52 +0100 Subject: [PATCH 6/8] added relative paths to pom in mutex/semaphore --- mutex/pom.xml | 1 + semaphore/pom.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/mutex/pom.xml b/mutex/pom.xml index 07c2d793c..6e418c1d1 100644 --- a/mutex/pom.xml +++ b/mutex/pom.xml @@ -30,6 +30,7 @@ <groupId>com.iluwatar</groupId> <artifactId>java-design-patterns</artifactId> <version>1.11.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> </parent> <artifactId>mutex</artifactId> <dependencies> diff --git a/semaphore/pom.xml b/semaphore/pom.xml index 14b551a1a..2d0bfb907 100644 --- a/semaphore/pom.xml +++ b/semaphore/pom.xml @@ -30,6 +30,7 @@ <groupId>com.iluwatar</groupId> <artifactId>java-design-patterns</artifactId> <version>1.11.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> </parent> <artifactId>semaphore</artifactId> <dependencies> From e821abdb1bc6e7a4238318bf89afb9cdb7810d95 Mon Sep 17 00:00:00 2001 From: gwildor28 <jbenedetti28@hotmail.com> Date: Thu, 14 Apr 2016 17:44:18 +0100 Subject: [PATCH 7/8] updated version to fix pom --- mutex/pom.xml | 3 +-- semaphore/pom.xml | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/mutex/pom.xml b/mutex/pom.xml index 6e418c1d1..c9e0e83b7 100644 --- a/mutex/pom.xml +++ b/mutex/pom.xml @@ -29,8 +29,7 @@ <parent> <groupId>com.iluwatar</groupId> <artifactId>java-design-patterns</artifactId> - <version>1.11.0-SNAPSHOT</version> - <relativePath>../pom.xml</relativePath> + <version>1.12.0-SNAPSHOT</version> </parent> <artifactId>mutex</artifactId> <dependencies> diff --git a/semaphore/pom.xml b/semaphore/pom.xml index 2d0bfb907..a2dc143a1 100644 --- a/semaphore/pom.xml +++ b/semaphore/pom.xml @@ -29,8 +29,7 @@ <parent> <groupId>com.iluwatar</groupId> <artifactId>java-design-patterns</artifactId> - <version>1.11.0-SNAPSHOT</version> - <relativePath>../pom.xml</relativePath> + <version>1.12.0-SNAPSHOT</version> </parent> <artifactId>semaphore</artifactId> <dependencies> From a2843297d872df89c2d25a96bf12eb13a3852a28 Mon Sep 17 00:00:00 2001 From: gwildor28 <jbenedetti28@hotmail.com> Date: Sun, 17 Apr 2016 14:46:52 +0100 Subject: [PATCH 8/8] JUnit tests --- .../src/main/java/com/iluwatar/mutex/App.java | 2 +- .../src/main/java/com/iluwatar/mutex/Jar.java | 7 ++- .../main/java/com/iluwatar/mutex/Mutex.java | 13 ++++- .../main/java/com/iluwatar/mutex/Thief.java | 2 +- .../test/java/com/iluwatar/mutex/JarTest.java | 43 ++++++++++++++ .../java/com/iluwatar/mutex/MutexTest.java | 47 ++++++++++++++++ .../com/iluwatar/semaphore/Semaphore.java | 26 +++++++-- .../com/iluwatar/semaphore/FruitBowlTest.java | 51 +++++++++++++++++ .../com/iluwatar/semaphore/SemaphoreTest.java | 56 +++++++++++++++++++ 9 files changed, 236 insertions(+), 11 deletions(-) create mode 100644 mutex/src/test/java/com/iluwatar/mutex/JarTest.java create mode 100644 mutex/src/test/java/com/iluwatar/mutex/MutexTest.java create mode 100644 semaphore/src/test/java/com/iluwatar/semaphore/FruitBowlTest.java create mode 100644 semaphore/src/test/java/com/iluwatar/semaphore/SemaphoreTest.java diff --git a/mutex/src/main/java/com/iluwatar/mutex/App.java b/mutex/src/main/java/com/iluwatar/mutex/App.java index 559453500..f6494bd5c 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/App.java +++ b/mutex/src/main/java/com/iluwatar/mutex/App.java @@ -40,7 +40,7 @@ public class App { */ public static void main(String[] args) { Mutex mutex = new Mutex(); - Jar jar = new Jar(mutex); + Jar jar = new Jar(1000, mutex); Thief peter = new Thief("Peter", jar); Thief john = new Thief("John", jar); peter.start(); diff --git a/mutex/src/main/java/com/iluwatar/mutex/Jar.java b/mutex/src/main/java/com/iluwatar/mutex/Jar.java index e049b7a75..4fe0a4637 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Jar.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Jar.java @@ -37,16 +37,17 @@ public class Jar { /** * The resource within the jar. */ - private int beans = 1000; + private int beans; - public Jar(Lock lock) { + public Jar(int beans, Lock lock) { + this.beans = beans; this.lock = lock; } /** * Method for a thief to take a bean. */ - public boolean takeBean(Thief thief) { + public boolean takeBean() { boolean success = false; try { lock.acquire(); diff --git a/mutex/src/main/java/com/iluwatar/mutex/Mutex.java b/mutex/src/main/java/com/iluwatar/mutex/Mutex.java index e15deaf48..8e08534cd 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Mutex.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Mutex.java @@ -32,6 +32,13 @@ public class Mutex implements Lock { */ private Object owner; + /** + * Returns the current owner of the Mutex, or null if available + */ + public Object getOwner() { + return owner; + } + /** * Method called by a thread to acquire the lock. If the lock has already * been acquired this will wait until the lock has been released to @@ -51,8 +58,10 @@ public class Mutex implements Lock { */ @Override public synchronized void release() { - owner = null; - notify(); + if (Thread.currentThread() == owner) { + owner = null; + notify(); + } } } diff --git a/mutex/src/main/java/com/iluwatar/mutex/Thief.java b/mutex/src/main/java/com/iluwatar/mutex/Thief.java index 58ce019e0..d2225876c 100644 --- a/mutex/src/main/java/com/iluwatar/mutex/Thief.java +++ b/mutex/src/main/java/com/iluwatar/mutex/Thief.java @@ -51,7 +51,7 @@ public class Thief extends Thread { public void run() { int beans = 0; - while (jar.takeBean(this)) { + while (jar.takeBean()) { beans = beans + 1; System.out.println(name + " took a bean."); } diff --git a/mutex/src/test/java/com/iluwatar/mutex/JarTest.java b/mutex/src/test/java/com/iluwatar/mutex/JarTest.java new file mode 100644 index 000000000..97101466a --- /dev/null +++ b/mutex/src/test/java/com/iluwatar/mutex/JarTest.java @@ -0,0 +1,43 @@ +/** + * 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.mutex; + +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * Test case for taking beans from a Jar + */ +public class JarTest { + + @Test + public void testTakeBeans() { + Mutex mutex = new Mutex(); + Jar jar = new Jar(10, mutex); + for (int i = 0; i < 10; i++) { + assertTrue(jar.takeBean()); + } + assertFalse(jar.takeBean()); + } + +} \ No newline at end of file diff --git a/mutex/src/test/java/com/iluwatar/mutex/MutexTest.java b/mutex/src/test/java/com/iluwatar/mutex/MutexTest.java new file mode 100644 index 000000000..8b3e82cb4 --- /dev/null +++ b/mutex/src/test/java/com/iluwatar/mutex/MutexTest.java @@ -0,0 +1,47 @@ +/** + * 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.mutex; + +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * Test case for acquiring and releasing a Mutex + */ +public class MutexTest { + + @Test + public void acquireReleaseTest() { + Mutex mutex = new Mutex(); + assertNull(mutex.getOwner()); + try { + mutex.acquire(); + assertEquals(mutex.getOwner(), Thread.currentThread()); + } catch (InterruptedException e) { + fail(e.toString()); + } + mutex.release(); + assertNull(mutex.getOwner()); + } + +} \ No newline at end of file diff --git a/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java b/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java index 79f3b4465..2e4a54c7c 100644 --- a/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java +++ b/semaphore/src/main/java/com/iluwatar/semaphore/Semaphore.java @@ -27,13 +27,29 @@ package com.iluwatar.semaphore; */ public class Semaphore implements Lock { + private final int licenses; /** * The number of concurrent resource accesses which are allowed. */ private int counter; - public Semaphore(int counter) { - this.counter = counter; + public Semaphore(int licenses) { + this.licenses = licenses; + this.counter = licenses; + } + + /** + * Returns the number of licenses managed by the Semaphore + */ + public int getNumLicenses() { + return licenses; + } + + /** + * Returns the number of available licenses + */ + public int getAvailableLicenses() { + return counter; } /** @@ -52,8 +68,10 @@ public class Semaphore implements Lock { * Method called by a thread to release the lock. */ public synchronized void release() { - counter = counter + 1; - notify(); + if (counter < licenses) { + counter = counter + 1; + notify(); + } } } diff --git a/semaphore/src/test/java/com/iluwatar/semaphore/FruitBowlTest.java b/semaphore/src/test/java/com/iluwatar/semaphore/FruitBowlTest.java new file mode 100644 index 000000000..be31f77ab --- /dev/null +++ b/semaphore/src/test/java/com/iluwatar/semaphore/FruitBowlTest.java @@ -0,0 +1,51 @@ +/** + * 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.semaphore; + +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * Test taking from and putting Fruit into a FruitBowl + */ +public class FruitBowlTest { + + @Test + public void fruitBowlTest() { + FruitBowl fbowl = new FruitBowl(); + + assertEquals(fbowl.countFruit(), 0); + + for (int i = 1; i <= 10; i++) { + fbowl.put(new Fruit(Fruit.FruitType.LEMON)); + assertEquals(fbowl.countFruit(), i); + } + + for (int i = 9; i >= 0; i--) { + assertNotNull(fbowl.take()); + assertEquals(fbowl.countFruit(), i); + } + + assertNull(fbowl.take()); + } +} diff --git a/semaphore/src/test/java/com/iluwatar/semaphore/SemaphoreTest.java b/semaphore/src/test/java/com/iluwatar/semaphore/SemaphoreTest.java new file mode 100644 index 000000000..14587a485 --- /dev/null +++ b/semaphore/src/test/java/com/iluwatar/semaphore/SemaphoreTest.java @@ -0,0 +1,56 @@ +/** + * 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.semaphore; + +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * Test case for acquiring and releasing a Semaphore + */ +public class SemaphoreTest { + + @Test + public void acquireReleaseTest() { + Semaphore sphore = new Semaphore(3); + + assertEquals(sphore.getAvailableLicenses(), 3); + + for (int i = 2; i >= 0; i--) { + try { + sphore.acquire(); + assertEquals(sphore.getAvailableLicenses(), i); + } catch (InterruptedException e) { + fail(e.toString()); + } + } + + for (int i = 1; i <= 3; i++) { + sphore.release(); + assertEquals(sphore.getAvailableLicenses(), i); + } + + sphore.release(); + assertEquals(sphore.getAvailableLicenses(), 3); + } +}