Repository navigation
Expand file tree
/
Copy pathAssemblyLine.java
More file actions
158 lines (119 loc) · 5.01 KB
/
Copy pathAssemblyLine.java
File metadata and controls
158 lines (119 loc) · 5.01 KB
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
package modern.challenge;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
public final class AssemblyLine {
private AssemblyLine() {
throw new AssertionError("There is a single assembly line!");
}
private static final int BASKET_CAPACITY = 5;
private static final int MAX_PROD_TIME_MS = 2 * 1000;
private static final int MAX_CONS_TIME_MS = 5 * 1000;
private static final int TIMEOUT_MS = (MAX_PROD_TIME_MS + MAX_CONS_TIME_MS) * BASKET_CAPACITY;
private static final Logger logger = Logger.getLogger(AssemblyLine.class.getName());
private static final Random rnd = new Random();
private static final Producer producer = new Producer();
private static final Consumer consumer = new Consumer();
private static final Exchanger<List<String>> exchanger = new Exchanger<>();
private static volatile boolean runningProducer;
private static volatile boolean runningConsumer;
private static ExecutorService producerService;
private static ExecutorService consumerService;
private static class Producer implements Runnable {
private List<String> basket = new ArrayList<>(BASKET_CAPACITY);
@Override
public void run() {
while (runningProducer) {
try {
for (int i = 0; i < BASKET_CAPACITY; i++) {
String bulb = "bulb-" + rnd.nextInt(1000);
Thread.sleep(rnd.nextInt(MAX_PROD_TIME_MS));
basket.add(bulb);
logger.info(() -> "Checked and added in the basket: " + bulb);
}
logger.info("Producer: Waiting to exchange baskets ...");
basket = exchanger.exchange(basket);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
logger.severe(() -> "Exception: " + ex);
break;
}
}
}
}
private static class Consumer implements Runnable {
private List<String> basket = new ArrayList<>(BASKET_CAPACITY);
@Override
public void run() {
while (runningConsumer) {
try {
logger.info("Consumer: Waiting to exchange baskets ...");
basket = exchanger.exchange(basket);
logger.info(() -> "Consumer: Received the following bulbs: " + basket);
for (String bulb : basket) {
if (bulb != null) {
Thread.sleep(rnd.nextInt(MAX_CONS_TIME_MS));
logger.info(() -> "Packed from basket: " + bulb);
}
}
basket.clear();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
logger.severe(() -> "Exception: " + ex);
break;
}
}
}
}
public static void startAssemblyLine() {
if (runningProducer || runningConsumer) {
logger.info("Assembly line is already running ...");
return;
}
logger.info("\n\nStarting assembly line ...");
runningProducer = true;
producerService = Executors.newSingleThreadExecutor();
producerService.execute(producer);
runningConsumer = true;
consumerService = Executors.newSingleThreadExecutor();
consumerService.execute(consumer);
}
public static void stopAssemblyLine() {
logger.info("Stopping assembly line ...");
boolean isProducerDown = shutdownProducer();
boolean isConsumerDown = shutdownConsumer();
if (!isProducerDown || !isConsumerDown) {
logger.severe("Something abnormal happened during shutting down the assembling line!");
System.exit(0);
}
logger.info("Assembling line was successfully stopped!");
}
private static boolean shutdownProducer() {
runningProducer = false;
return shutdownExecutor(producerService);
}
private static boolean shutdownConsumer() {
runningConsumer = false;
return shutdownExecutor(consumerService);
}
private static boolean shutdownExecutor(ExecutorService executor) {
executor.shutdown();
try {
if (!executor.awaitTermination(TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
executor.shutdownNow();
return executor.awaitTermination(TIMEOUT_MS, TimeUnit.MILLISECONDS);
}
return true;
} catch (InterruptedException ex) {
executor.shutdownNow();
Thread.currentThread().interrupt();
logger.severe(() -> "Exception: " + ex);
}
return false;
}
}