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 package org.slf4j.nop;
26
27 import static org.junit.Assert.assertEquals;
28
29 import java.io.PrintStream;
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.Random;
33 import java.util.concurrent.BrokenBarrierException;
34 import java.util.concurrent.CyclicBarrier;
35 import java.util.concurrent.atomic.AtomicLong;
36
37 import org.junit.After;
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42 import org.slf4j.LoggerFactoryFriend;
43
44 public class MultithreadedInitializationTest {
45
46 final static int THREAD_COUNT = 4 + Runtime.getRuntime().availableProcessors() * 2;
47
48 private static final AtomicLong EVENT_COUNT = new AtomicLong(0);
49
50 final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
51
52 int diff = new Random().nextInt(10000);
53 String loggerName = "org.slf4j.impl.MultithreadedInitializationTest";
54 private final PrintStream oldErr = System.err;
55 StringPrintStream sps = new StringPrintStream(oldErr);
56
57 @Before
58 public void setup() {
59 LoggerFactoryFriend.reset();
60 System.setErr(sps);
61 }
62
63 @After
64 public void tearDown() throws Exception {
65 LoggerFactoryFriend.reset();
66 System.setErr(oldErr);
67 }
68
69 @Test
70 public void multiThreadedInitialization() throws InterruptedException, BrokenBarrierException {
71 System.out.println("THREAD_COUNT=" + THREAD_COUNT);
72 LoggerAccessingThread[] accessors = harness();
73
74 for (LoggerAccessingThread accessor : accessors) {
75 EVENT_COUNT.getAndIncrement();
76 accessor.logger.info("post harness");
77 }
78
79 Logger logger = LoggerFactory.getLogger(loggerName + ".slowInitialization-" + diff);
80 logger.info("hello");
81 EVENT_COUNT.getAndIncrement();
82
83 assertEquals(0, sps.stringList.size());
84 }
85
86 private static LoggerAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
87 LoggerAccessingThread[] threads = new LoggerAccessingThread[THREAD_COUNT];
88 final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
89 for (int i = 0; i < THREAD_COUNT; i++) {
90 threads[i] = new LoggerAccessingThread(barrier, i);
91 threads[i].start();
92 }
93
94 barrier.await();
95 for (int i = 0; i < THREAD_COUNT; i++) {
96 threads[i].join();
97 }
98 return threads;
99 }
100
101 static class LoggerAccessingThread extends Thread {
102 final CyclicBarrier barrier;
103 Logger logger;
104 int count;
105
106 LoggerAccessingThread(CyclicBarrier barrier, int count) {
107 this.barrier = barrier;
108 this.count = count;
109 }
110
111 public void run() {
112 try {
113 barrier.await();
114 } catch (Exception e) {
115 e.printStackTrace();
116 }
117 logger = LoggerFactory.getLogger(this.getClass().getName() + "-" + count);
118 logger.info("in run method");
119 EVENT_COUNT.getAndIncrement();
120 }
121 };
122
123 public static class StringPrintStream extends PrintStream {
124
125 public static final String LINE_SEP = System.getProperty("line.separator");
126 PrintStream other;
127 List<String> stringList = new ArrayList<>();
128
129 public StringPrintStream(PrintStream ps) {
130 super(ps);
131 other = ps;
132 }
133
134 public void print(String s) {
135 other.print(s);
136 stringList.add(s);
137 }
138
139 public void println(String s) {
140 other.println(s);
141 stringList.add(s);
142 }
143
144 public void println(Object o) {
145 other.println(o);
146 stringList.add(o.toString());
147 }
148 };
149
150 }