diff --git a/monitor/README.md b/monitor/README.md deleted file mode 100644 index 59eb2ba0c..000000000 --- a/monitor/README.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -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 deleted file mode 100644 index c00e70e3f..000000000 Binary files a/monitor/etc/monitor.urm.png and /dev/null differ diff --git a/monitor/etc/monitor.urm.puml b/monitor/etc/monitor.urm.puml deleted file mode 100644 index 075ef8520..000000000 --- a/monitor/etc/monitor.urm.puml +++ /dev/null @@ -1,12 +0,0 @@ -@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 deleted file mode 100644 index 46e10f17d..000000000 --- a/monitor/pom.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - 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 deleted file mode 100644 index d4defa6d1..000000000 --- a/monitor/src/main/java/com/iluwatar/monitor/Bank.java +++ /dev/null @@ -1,37 +0,0 @@ -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 deleted file mode 100644 index c1e1bcccb..000000000 --- a/monitor/src/main/java/com/iluwatar/monitor/Main.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 deleted file mode 100644 index eab7d7a3c..000000000 --- a/monitor/src/main/test/java/com/iluwater/java/BankTest.java +++ /dev/null @@ -1,55 +0,0 @@ -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; - } - -}