1
- /*
2
- * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
3
- *
4
- * The MIT License
5
- * Copyright © 2014-2022 Ilkka Seppälä
6
- *
7
- * Permission is hereby granted, free of charge, to any person obtaining a copy
8
- * of this software and associated documentation files (the "Software"), to deal
9
- * in the Software without restriction, including without limitation the rights
10
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- * copies of the Software, and to permit persons to whom the Software is
12
- * furnished to do so, subject to the following conditions:
13
- *
14
- * The above copyright notice and this permission notice shall be included in
15
- * all copies or substantial portions of the Software.
16
- *
17
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- * THE SOFTWARE.
24
- */
25
1
package com .iluwatar .leaderfollowers ;
26
2
27
3
import java .security .SecureRandom ;
28
4
import java .util .concurrent .Executors ;
29
5
import java .util .concurrent .TimeUnit ;
6
+ import lombok .extern .slf4j .Slf4j ;
30
7
31
- /**
32
- * Leader/Followers pattern is a concurrency pattern. This pattern behaves like a taxi stand where
33
- * one of the threads acts as leader thread which listens for event from event sources,
34
- * de-multiplexes, dispatches and handles the event. It promotes the follower to be the new leader.
35
- * When processing completes the thread joins the followers queue, if there are no followers then it
36
- * becomes the leader and cycle repeats again.
37
- *
38
- * <p>In this example, one of the workers becomes Leader and listens on the {@link TaskSet} for
39
- * work. {@link TaskSet} basically acts as the source of input events for the {@link Worker}, who
40
- * are spawned and controlled by the {@link WorkCenter} . When {@link Task} arrives then the leader
41
- * takes the work and calls the {@link TaskHandler}. It also calls the {@link WorkCenter} to
42
- * promotes one of the followers to be the new leader, who can then process the next work and so on.
43
- *
44
- * <p>The pros for this pattern are: It enhances CPU cache affinity and eliminates unbound
45
- * allocation and data buffer sharing between threads by reading the request into buffer space
46
- * allocated on the stack of the leader or by using the Thread-Specific Storage pattern [22] to
47
- * allocate memory. It minimizes locking overhead by not exchanging data between threads, thereby
48
- * reducing thread synchronization. In bound handle/thread associations, the leader thread
49
- * dispatches the event based on the I/O handle. It can minimize priority inversion because no extra
50
- * queuing is introduced in the server. It does not require a context switch to handle each event,
51
- * reducing the event dispatching latency. Note that promoting a follower thread to fulfill the
52
- * leader role requires a context switch. Programming simplicity: The Leader/Followers pattern
53
- * simplifies the programming of concurrency models where multiple threads can receive requests,
54
- * process responses, and de-multiplex connections using a shared handle set.
55
- */
8
+ @ Slf4j
56
9
public class App {
57
10
58
- /** The main method for the leader followers pattern. */
59
11
public static void main (String [] args ) throws InterruptedException {
60
12
var taskSet = new TaskSet ();
61
13
var taskHandler = new TaskHandler ();
@@ -64,18 +16,23 @@ public static void main(String[] args) throws InterruptedException {
64
16
execute (workCenter , taskSet );
65
17
}
66
18
67
- /** Start the work, dispatch tasks and stop the thread pool at last. */
68
19
private static void execute (WorkCenter workCenter , TaskSet taskSet ) throws InterruptedException {
69
20
var workers = workCenter .getWorkers ();
70
21
var exec = Executors .newFixedThreadPool (workers .size ());
71
- workers .forEach (exec ::submit );
72
- Thread .sleep (1000 );
73
- addTasks (taskSet );
74
- exec .awaitTermination (2 , TimeUnit .SECONDS );
75
- exec .shutdownNow ();
22
+
23
+ try {
24
+ workers .forEach (exec ::submit );
25
+ Thread .sleep (1000 );
26
+ addTasks (taskSet );
27
+ boolean terminated = exec .awaitTermination (2 , TimeUnit .SECONDS );
28
+ if (!terminated ) {
29
+ LOGGER .warn ("Executor did not terminate in the given time." );
30
+ }
31
+ } finally {
32
+ exec .shutdownNow ();
33
+ }
76
34
}
77
35
78
- /** Add tasks. */
79
36
private static void addTasks (TaskSet taskSet ) throws InterruptedException {
80
37
var rand = new SecureRandom ();
81
38
for (var i = 0 ; i < 5 ; i ++) {
0 commit comments