View Javadoc

    1   /**
    2    * Copyright (c) 2004-2016 QOS.ch
    3    * All rights reserved.
    4    *
    5    * Permission is hereby granted, free  of charge, to any person obtaining
    6    * a  copy  of this  software  and  associated  documentation files  (the
    7    * "Software"), to  deal in  the Software without  restriction, including
    8    * without limitation  the rights to  use, copy, modify,  merge, publish,
    9    * distribute,  sublicense, and/or sell  copies of  the Software,  and to
    10   * permit persons to whom the Software  is furnished to do so, subject to
    11   * the following conditions:
    12   *
    13   * The  above  copyright  notice  and  this permission  notice  shall  be
    14   * included in all copies or substantial portions of the Software.
    15   *
    16   * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
    17   * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
    18   * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
    19   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    20   * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    21   * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
    22   * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    23   *
    24   */
    25  package org.slf4j.impl;
    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 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<String>();
    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 }