-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAccountManager.java
146 lines (129 loc) · 4.39 KB
/
AccountManager.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
* Name: Jose Tapizquent
* Course: CNT 4714 Spring 2021
* Assignment Title: Project 2 - Synchronized, Cooperating Threads Under Locking
* Due Date: February 14, 2021
*
* AccountManager.java
*/
import java.util.concurrent.locks.*;
public class AccountManager {
/**
* Manages the account by allowing only one thread at a time to access the
* [currentBalance] in order to keep synchronization among all threads.
*
* Initializes the account with a balance of 0.
*/
public AccountManager() {
this(0);
}
/**
* Manages the account by allowing only one thread at a time to access the
* [currentBalance] in order to keep synchronization among all threads.
*
* @param initialBalance The initial balance on the account
*/
public AccountManager(int initialBalance) {
currentBalance = 0;
}
private int currentBalance;
private Lock accessLock = new ReentrantLock();
private Condition canWithdraw = accessLock.newCondition();
private Condition canDeposit = accessLock.newCondition();
private boolean isBusy = false;
/**
* Performs deposit if account is not currently busy being accessed by another
* resource.
*
* Returns the currentBalance to depositor only for displaying purposes.
*
*
* @param depositAmount The amount to be deposited into the account
* @return currentBalance of the account after deposit
*/
public int deposit(int depositAmount) {
accessLock.lock();
/**
* If this thread gets the accessLock, it checks whether the account is
* currently being accessed by another thread and if it is, waits for a
* [canDeposit] signal in order to proceed and make a deposit.
*/
while (isBusy) {
try {
System.out.println("Manager occupied. Deposit Waiting...");
canDeposit.await();
isBusy = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Deposit into [currentBalance].
*/
currentBalance += depositAmount;
/**
* Signal other threads that this one is done doing deposits and unlock
* accessLock.
*/
canWithdraw.signalAll();
canDeposit.signalAll();
accessLock.unlock();
/**
* Return currentBalance to depositor for displaying purposes.
*/
return currentBalance;
}
/**
* Makes a withdrawal is the service is currently not being accessed by another
* resource.
*
* Returns the withdrew amount if there are enough funds in the account. Returns
* 0 if there are not enough funds to return the withdrawAmount.
*
* @param withdrawAmount The amount to be withdrew from the account balance
* @return The withdrew amount if there are enough funds or 0 otherwise.
*/
public int withdraw(int withdrawAmount) {
accessLock.lock();
/**
* If this thread gets the accessLock, it checks whether the account is
* currently being accessed by another thread and if it is, waits for a
* [canWithdraw] signal in order to proceed and make a withdrawal.
*/
while (isBusy) {
try {
System.out.println("Manager occupied. Withdrawal Waiting...");
canWithdraw.await();
isBusy = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* If the [currentBalance] is less than the [withdrawAmount], it returns 0 and
* signals other resources that it is done as there are not enough funds to
* withdraw.
*/
if (currentBalance - withdrawAmount < 0) {
canWithdraw.signalAll();
canDeposit.signalAll();
accessLock.unlock();
return 0;
}
/**
* Withdraw from [currentBalance].
*/
currentBalance -= withdrawAmount;
/**
* Signal other threads that this one is done doing deposits and unlock
* accessLock.
*/
canWithdraw.signalAll();
canDeposit.signalAll();
accessLock.unlock();
return withdrawAmount;
}
public int getCurrentBalance() {
return currentBalance;
}
}