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- */
251package com .iluwatar .leaderfollowers ;
262
273import java .security .SecureRandom ;
284import java .util .concurrent .Executors ;
295import java .util .concurrent .TimeUnit ;
6+ import lombok .extern .slf4j .Slf4j ;
7+ import org .slf4j .Logger ;
8+ import org .slf4j .LoggerFactory ;
309
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- */
10+ @ Slf4j
5611public class App {
12+ private static final Logger log = LoggerFactory .getLogger (App .class );
5713
58- /** The main method for the leader followers pattern. */
5914 public static void main (String [] args ) throws InterruptedException {
6015 var taskSet = new TaskSet ();
6116 var taskHandler = new TaskHandler ();
@@ -64,7 +19,6 @@ public static void main(String[] args) throws InterruptedException {
6419 execute (workCenter , taskSet );
6520 }
6621
67- /** Start the work, dispatch tasks and stop the thread pool at last. */
6822 private static void execute (WorkCenter workCenter , TaskSet taskSet ) throws InterruptedException {
6923 var workers = workCenter .getWorkers ();
7024 var exec = Executors .newFixedThreadPool (workers .size ());
@@ -75,14 +29,13 @@ private static void execute(WorkCenter workCenter, TaskSet taskSet) throws Inter
7529 addTasks (taskSet );
7630 boolean terminated = exec .awaitTermination (2 , TimeUnit .SECONDS );
7731 if (!terminated ) {
78- System . out . println ("Executor did not terminate in the given time." );
32+ log . warn ("Executor did not terminate in the given time." );
7933 }
8034 } finally {
8135 exec .shutdownNow ();
8236 }
8337 }
8438
85- /** Add tasks. */
8639 private static void addTasks (TaskSet taskSet ) throws InterruptedException {
8740 var rand = new SecureRandom ();
8841 for (var i = 0 ; i < 5 ; i ++) {
0 commit comments