-
Notifications
You must be signed in to change notification settings - Fork 2
/
SleepingBarber.java
271 lines (196 loc) · 9.65 KB
/
SleepingBarber.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class SleepingBarber {
public static void main (String a[]) throws InterruptedException {
int noOfBarbers=2, customerId=1, noOfCustomers=100, noOfChairs; //initializing the number of barber and customers
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number of barbers(M):"); //input M barbers
noOfBarbers=sc.nextInt();
System.out.println("Enter the number of waiting room" //input N waiting chairs
+ " chairs(N):");
noOfChairs=sc.nextInt();
// System.out.println("Enter the number of customers:"); //inout the number of customers for the shop
// noOfCustomers=sc.nextInt();
ExecutorService exec = Executors.newFixedThreadPool(12); //initializing with 12 threads as multiple of cores in the CPU, here 6
Bshop shop = new Bshop(noOfBarbers, noOfChairs); //initializing the barber shop with the number of barbers
Random r = new Random(); //a random number to calculate delays for customer arrivals and haircut
System.out.println("\nBarber shop opened with "
+noOfBarbers+" barber(s)\n");
long startTime = System.currentTimeMillis(); //start time of program
for(int i=1; i<=noOfBarbers;i++) { //generating the specified number of threads for barber
Barber barber = new Barber(shop, i);
Thread thbarber = new Thread(barber);
exec.execute(thbarber);
}
for(int i=0;i<noOfCustomers;i++) { //customer generator; generating customer threads
Customer customer = new Customer(shop);
customer.setInTime(new Date());
Thread thcustomer = new Thread(customer);
customer.setcustomerId(customerId++);
exec.execute(thcustomer);
try {
double val = r.nextGaussian() * 2000 + 2000; //'r':object of Random class, nextGaussian() generates a number with mean 2000 and
int millisDelay = Math.abs((int) Math.round(val)); //standard deviation as 2000, thus customers arrive at mean of 2000 milliseconds
Thread.sleep(millisDelay); //and standard deviation of 2000 milliseconds
}
catch(InterruptedException iex) {
iex.printStackTrace();
}
}
exec.shutdown(); //shuts down the executor service and frees all the resources
exec.awaitTermination(12, SECONDS); //waits for 12 seconds until all the threads finish their execution
long elapsedTime = System.currentTimeMillis() - startTime; //to calculate the end time of program
System.out.println("\nBarber shop closed");
System.out.println("\nTotal time elapsed in seconds"
+ " for serving "+noOfCustomers+" customers by "
+noOfBarbers+" barbers with "+noOfChairs+
" chairs in the waiting room is: "
+TimeUnit.MILLISECONDS
.toSeconds(elapsedTime));
System.out.println("\nTotal customers: "+noOfCustomers+
"\nTotal customers served: "+shop.getTotalHairCuts()
+"\nTotal customers lost: "+shop.getCustomerLost());
sc.close();
}
}
class Barber implements Runnable { // initializing the barber
Bshop shop;
int barberId;
public Barber(Bshop shop, int barberId) {
this.shop = shop;
this.barberId = barberId;
}
public void run() {
while(true) {
shop.cutHair(barberId);
}
}
}
class Customer implements Runnable {
int customerId;
Date inTime;
Bshop shop;
public Customer(Bshop shop) {
this.shop = shop;
}
public int getCustomerId() { //getter and setter methods
return customerId;
}
public Date getInTime() {
return inTime;
}
public void setcustomerId(int customerId) {
this.customerId = customerId;
}
public void setInTime(Date inTime) {
this.inTime = inTime;
}
public void run() { //customer thread goes to the shop for the haircut
goForHairCut();
}
private synchronized void goForHairCut() { //customer is added to the list
shop.add(this);
}
}
class Bshop {
private final AtomicInteger totalHairCuts = new AtomicInteger(0);
private final AtomicInteger customersLost = new AtomicInteger(0);
int nchair, noOfBarbers, availableBarbers;
List<Customer> listCustomer;
Random r = new Random();
public Bshop(int noOfBarbers, int noOfChairs){
this.nchair = noOfChairs; //number of chairs in the waiting room
listCustomer = new LinkedList<Customer>(); //list to store the arriving customers
this.noOfBarbers = noOfBarbers; //initializing the the total number of barbers
availableBarbers = noOfBarbers;
}
public AtomicInteger getTotalHairCuts() {
totalHairCuts.get();
return totalHairCuts;
}
public AtomicInteger getCustomerLost() {
customersLost.get();
return customersLost;
}
public void cutHair(int barberId)
{
Customer customer;
synchronized (listCustomer) { //listCustomer is a shared resource so it has been synchronized to avoid any
//unexpected errors in the list when multiple threads access it
while(listCustomer.size()==0) {
System.out.println("\nBarber "+barberId+" is waiting "
+ "for the customer and sleeps in his chair");
try {
listCustomer.wait(); //barber sleeps if there are no customers in the shop
}
catch(InterruptedException iex) {
iex.printStackTrace();
}
}
customer = (Customer)((LinkedList<?>)listCustomer).poll(); //takes the first customer from the head of the list for haircut
System.out.println("Customer "+customer.getCustomerId()+
" finds the barber asleep and wakes up "
+ "the barber "+barberId);
}
int millisDelay=0;
try {
availableBarbers--; //decreases the count of the available barbers as one of them starts
//cutting hair of the customer and the customer sleeps
System.out.println("Barber "+barberId+" cutting hair of "+
customer.getCustomerId()+ " so customer sleeps");
double val = r.nextGaussian() * 2000 + 4000; //time taken to cut the customer's hair has a mean of 4000 milliseconds and
millisDelay = Math.abs((int) Math.round(val)); //and standard deviation of 2000 milliseconds
Thread.sleep(millisDelay);
System.out.println("\nCompleted Cutting hair of "+
customer.getCustomerId()+" by barber " +
barberId +" in "+millisDelay+ " milliseconds.");
totalHairCuts.incrementAndGet();
//exits through the door
if(listCustomer.size()>0) {
System.out.println("Barber "+barberId+ //barber finds a sleeping customer in the waiting room, wakes him up and
" wakes up a customer in the " //and then goes to his chair and sleeps until a customer arrives
+ "waiting room");
}
availableBarbers++; //barber is available for haircut for the next customer
}
catch(InterruptedException iex) {
iex.printStackTrace();
}
}
public void add(Customer customer) {
System.out.println("\nCustomer "+customer.getCustomerId()+
" enters through the entrance door in the the shop at "
+customer.getInTime());
synchronized (listCustomer) {
if(listCustomer.size() == nchair) { //No chairs are available for the customer so the customer leaves the shop
System.out.println("\nNo chair available "
+ "for customer "+customer.getCustomerId()+
" so customer leaves the shop");
customersLost.incrementAndGet();
return;
}
else if (availableBarbers > 0) { //If barber is available then the customer wakes up the barber and sits in
//the chair
((LinkedList<Customer>)listCustomer).offer(customer);
listCustomer.notify();
}
else { //If barbers are busy and there are chairs in the waiting room then the customer
//sits on the chair in the waiting room
((LinkedList<Customer>)listCustomer).offer(customer);
System.out.println("All barber(s) are busy so "+
customer.getCustomerId()+
" takes a chair in the waiting room");
if(listCustomer.size()==1)
listCustomer.notify();
}
}
}
}