From c2786e5dc4a295ce771e79fce9b2e7fccf6fd0cc Mon Sep 17 00:00:00 2001 From: Ali Ghasemi <60359433+Dev-AliGhasemi@users.noreply.github.com> Date: Sat, 16 Oct 2021 10:08:53 -0700 Subject: [PATCH] add monitor design pattern (#1640) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add monitor design pattern . * add extra line and change compiler version to 11 in pom.xml. * encapsulate getBalance method . * update puml file . * export uml as png . * duplicate codes eliminated . * update tag * change the format of pom.xml * using logger to print * change AtomicRefrence to type inference var * explanations added ! * Update monitor/README.md Co-authored-by: Ilkka Seppälä * Update monitor/README.md Co-authored-by: Ilkka Seppälä * Update monitor/src/main/java/com/iluwatar/monitor/Main.java Co-authored-by: Ilkka Seppälä * Update monitor/src/main/java/com/iluwatar/monitor/Main.java Co-authored-by: Ilkka Seppälä * Update monitor/src/main/java/com/iluwatar/monitor/Main.java Co-authored-by: Ilkka Seppälä * Update monitor/src/main/java/com/iluwatar/monitor/Main.java Co-authored-by: Ilkka Seppälä * e.printStackTrace have changed to logger to prints standard output (STD OUT) . * add programmatic example . * Delete mvnw * mvnw.cmd deleted . * added mvnw from master * AddUnitTest * Add language to readme.md Co-authored-by: Subhrodip Mohanta Co-authored-by: Ilkka Seppälä Co-authored-by: Subhrodip Mohanta Co-authored-by: Subhrodip Mohanta --- monitor/README.md | 71 ++++++++++++++++++ monitor/etc/monitor.urm.png | Bin 0 -> 10483 bytes monitor/etc/monitor.urm.puml | 12 +++ monitor/pom.xml | 59 +++++++++++++++ .../main/java/com/iluwatar/monitor/Bank.java | 37 +++++++++ .../main/java/com/iluwatar/monitor/Main.java | 60 +++++++++++++++ .../test/java/com/iluwater/java/BankTest.java | 55 ++++++++++++++ 7 files changed, 294 insertions(+) create mode 100644 monitor/README.md create mode 100644 monitor/etc/monitor.urm.png create mode 100644 monitor/etc/monitor.urm.puml create mode 100644 monitor/pom.xml create mode 100644 monitor/src/main/java/com/iluwatar/monitor/Bank.java create mode 100644 monitor/src/main/java/com/iluwatar/monitor/Main.java create mode 100644 monitor/src/main/test/java/com/iluwater/java/BankTest.java diff --git a/monitor/README.md b/monitor/README.md new file mode 100644 index 000000000..59eb2ba0c --- /dev/null +++ b/monitor/README.md @@ -0,0 +1,71 @@ +--- +layout: pattern +title: Monitor +folder: monitor +permalink: /patterns/monitor/ +categories: Concurrency +language: en +tags: + - Performance +--- + +## Intent +Monitor pattern is used to create thread-safe objects and prevent conflicts between threads in concurrent applications. + +## Explanation + +In plain words + +> Monitor pattern is used to enforce single-threaded access to data. Only one thread at a time is allowed to execute code within the monitor object. + +Wikipedia says + +> In concurrent programming (also known as parallel programming), a monitor is a synchronization construct that allows threads to have both mutual exclusion and the ability to wait (block) for a certain condition to become false. Monitors also have a mechanism for signaling other threads that their condition has been met. + +**Programmatic Examples** + +Consider there is a bank that transfers money from an account to another account with transfer method . it is `synchronized` mean just one thread can access to this method because if many threads access to it and transfer money from an account to another account in same time balance changed ! + +``` +class Bank { + + private int[] accounts; + Logger logger; + + public Bank(int accountNum, int baseAmount, Logger logger) { + this.logger = logger; + accounts = new int[accountNum]; + Arrays.fill(accounts, baseAmount); + } + + public synchronized void transfer(int accountA, int accountB, int amount) { + if (accounts[accountA] >= amount) { + accounts[accountB] += amount; + accounts[accountA] -= amount; + logger.info("Transferred from account :" + accountA + " to account :" + accountB + " , amount :" + amount + " . balance :" + getBalance()); + } + } +``` + +getBalance always return total amount and the total amount should be same after each transfers + +``` + private synchronized int getBalance() { + int balance = 0; + for (int account : accounts) { + balance += account; + } + return balance; + } + } +``` + +## Class diagram +![alt text](./etc/monitor.urm.png "Monitor class diagram") + +## Applicability +Use the Monitor pattern when + +* we have a shared resource and there is critical section . +* you want to create thread-safe objects . +* you want to achieve mutual exclusion in high level programming language . diff --git a/monitor/etc/monitor.urm.png b/monitor/etc/monitor.urm.png new file mode 100644 index 0000000000000000000000000000000000000000..c00e70e3fd12cf01a074ecdf6cec3cccc79af721 GIT binary patch literal 10483 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 R2w>VEX>s}2-$eEO{tq4%7h(Va literal 0 HcmV?d00001 diff --git a/monitor/etc/monitor.urm.puml b/monitor/etc/monitor.urm.puml new file mode 100644 index 000000000..075ef8520 --- /dev/null +++ b/monitor/etc/monitor.urm.puml @@ -0,0 +1,12 @@ +@startuml +Main - Bank : use +class Main{ + + main(args : String[]) : void +} +class Bank{ + - accounts : int[] + + Bank (accountNum : int , baseAccount : int) + + transfer(accountA : int , accountB : int , amount : int) : void {synchronized} + - getBalance() : void {synchronized} +} +@enduml diff --git a/monitor/pom.xml b/monitor/pom.xml new file mode 100644 index 000000000..46e10f17d --- /dev/null +++ b/monitor/pom.xml @@ -0,0 +1,59 @@ + + + + 4.0.0 + + java-design-patterns + com.iluwatar + 1.24.0-SNAPSHOT + + monitor + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + + + + com.iluwatar.abstractdocument.Main + + + + + + + + + diff --git a/monitor/src/main/java/com/iluwatar/monitor/Bank.java b/monitor/src/main/java/com/iluwatar/monitor/Bank.java new file mode 100644 index 000000000..d4defa6d1 --- /dev/null +++ b/monitor/src/main/java/com/iluwatar/monitor/Bank.java @@ -0,0 +1,37 @@ +package com.iluwatar.monitor; + +import java.util.Arrays; +import java.util.logging.Logger; + +// Bank class implements the Monitor pattern +public class Bank { + + private int[] accounts; + Logger logger; + + public Bank(int accountNum, int baseAmount, Logger logger) { + this.logger = logger; + accounts = new int[accountNum]; + Arrays.fill(accounts, baseAmount); + } + + public synchronized void transfer(int accountA, int accountB, int amount) { + if (accounts[accountA] >= amount) { + accounts[accountB] += amount; + accounts[accountA] -= amount; + logger.info("Transferred from account :" + accountA + " to account :" + accountB + " , amount :" + amount + " . balance :" + getBalance()); + } + } + + public synchronized int getBalance() { + int balance = 0; + for (int account : accounts) { + balance += account; + } + return balance; + } + + public int[] getAccounts() { + return accounts; + } +} diff --git a/monitor/src/main/java/com/iluwatar/monitor/Main.java b/monitor/src/main/java/com/iluwatar/monitor/Main.java new file mode 100644 index 000000000..c1e1bcccb --- /dev/null +++ b/monitor/src/main/java/com/iluwatar/monitor/Main.java @@ -0,0 +1,60 @@ +/* + * The MIT License + * Copyright © 2014-2021 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.monitor; + +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Logger; + +/** + *

The Monitor pattern is used in concurrent algorithms to achieve mutual exclusion.

+ * + *

Bank is a simple class that transfers money from an account to another account using + * {@link Bank#transfer}. It can also return the balance of the bank account stored in the bank.

+ * + *

Main class uses ThreadPool to run threads that do transactions on the bank accounts.

+ */ + +public class Main { + + public static void main(String[] args) { + Logger logger = Logger.getLogger("monitor"); + var bank = new Bank(4, 1000, logger); + Runnable runnable = () -> { + try { + Thread.sleep((long) (Math.random() * 1000)); + Random random = new Random(); + for (int i = 0; i < 1000000; i++) + bank.transfer(random.nextInt(4), random.nextInt(4), (int) (Math.random() * 1000)); + } catch (InterruptedException e) { + logger.info(e.getMessage()); + } + }; + ExecutorService executorService = Executors.newFixedThreadPool(5); + for (int i = 0; i < 5; i++) { + executorService.execute(runnable); + } + } +} \ No newline at end of file diff --git a/monitor/src/main/test/java/com/iluwater/java/BankTest.java b/monitor/src/main/test/java/com/iluwater/java/BankTest.java new file mode 100644 index 000000000..eab7d7a3c --- /dev/null +++ b/monitor/src/main/test/java/com/iluwater/java/BankTest.java @@ -0,0 +1,55 @@ +package com.iluwater.java; + +import com.iluwatar.monitor.Bank; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assumptions.*; + +import java.util.logging.Logger; + +public class BankTest { + + private static Bank bank; + private static final int ACCOUNT_NUM = 4; + private static final int BASE_AMOUNT = 1000; + private static final Logger LOGGER = Logger.getLogger("monitor"); + + @BeforeAll + public static void Setup() { + bank = new Bank(ACCOUNT_NUM, BASE_AMOUNT, LOGGER); + } + + @Test + public void GetAccountHaveNotBeNull() { + assertNotNull(bank.getAccounts()); + } + + @Test + public void LengthOfAccountsHaveToEqualsToAccountNumConstant() { + assumeTrue(bank.getAccounts() != null); + assertEquals(ACCOUNT_NUM, bank.getAccounts().length); + } + + @Test + public void TransferMethodHaveToTransferAmountFromAnAccountToOtherAccount() { + bank.transfer(0, 1, 1000); + int accounts[] = bank.getAccounts(); + assertEquals(0, accounts[0]); + assertEquals(2000, 2000); + } + + @Test + public void BalanceHaveToBeOK() { + assertEquals(4000, bank.getBalance()); + } + + + @AfterAll + public static void TearDown() { + bank = null; + } + +}