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
+
+
+## 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 000000000..c00e70e3f
Binary files /dev/null and b/monitor/etc/monitor.urm.png differ
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 @@
+
+
+
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; + } + +}