@@ -0,0 +1,2793 @@
+package de.is24.util.monitoring;%0D%0A%0D%0Aimport org.junit.Before;%0D%0Aimport org.junit.BeforeClass;%0D%0Aimport org.junit.Test;%0D%0Aimport java.text.NumberFormat;%0D%0Aimport java.util.Random;%0D%0Aimport java.util.concurrent.ScheduledThreadPoolExecutor;%0D%0Aimport java.util.concurrent.ThreadPoolExecutor;%0D%0Aimport java.util.concurrent.TimeUnit;%0D%0Aimport java.util.concurrent.atomic.AtomicLong;%0D%0A%0D%0A%0D%0Apublic class ConcurrentcyTest %7B%0D%0A  private static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance();%0D%0A%0D%0A  static %7B%0D%0A    NUMBER_FORMAT.setGroupingUsed(true);%0D%0A    NUMBER_FORMAT.setMinimumFractionDigits(3);%0D%0A    NUMBER_FORMAT.setMaximumFractionDigits(3);%0D%0A  %7D%0D%0A%0D%0A  private static final int THREADS = 10, RUNS = 50;%0D%0A%0D%0A  private ThreadPoolExecutor executor;%0D%0A  private Job observerJob, timerJob;%0D%0A  private Random rnd;%0D%0A%0D%0A  private AtomicLong timerSum;%0D%0A%0D%0A  @BeforeClass%0D%0A  public static void beforeClass() %7B%0D%0A    InApplicationMonitor.resetInstanceForTesting();%0D%0A  %7D%0D%0A%0D%0A  @Before%0D%0A  public void setUp() throws Exception %7B%0D%0A    this.observerJob = new ObserverJob();%0D%0A    this.timerJob = new TimerJob();%0D%0A    this.rnd = new Random();%0D%0A    this.timerSum = new AtomicLong();%0D%0A  %7D%0D%0A%0D%0A  @Test%0D%0A  public void testConcurency() throws InterruptedException %7B%0D%0A    createExecutor(10);%0D%0A%0D%0A    executeJobs(timerJob, observerJob);%0D%0A%0D%0A  %7D%0D%0A%0D%0A  private void createExecutor(int threads) %7B%0D%0A    this.executor = new ScheduledThreadPoolExecutor(threads);%0D%0A    this.executor.setMaximumPoolSize(threads);%0D%0A  %7D%0D%0A%0D%0A%0D%0A  private void executeJobs(Runnable... jobs) throws InterruptedException %7B%0D%0A    for (int i = 0; i %3C RUNS; i++) %7B%0D%0A      for (Runnable job : jobs) %7B%0D%0A        executor.execute(job);%0D%0A      %7D%0D%0A    %7D%0D%0A    executor.shutdown();%0D%0A%0D%0A    executor.awaitTermination(100, TimeUnit.SECONDS);%0D%0A  %7D%0D%0A%0D%0A  private abstract class Job implements Runnable %7B%0D%0A    public void run() %7B%0D%0A      doJob();%0D%0A    %7D%0D%0A%0D%0A    protected abstract void doJob();%0D%0A  %7D%0D%0A%0D%0A%0D%0A  private class ObserverJob extends Job %7B%0D%0A    @Override%0D%0A    protected void doJob() %7B%0D%0A      try %7B%0D%0A        InApplicationMonitor.getInstance().addReportableObserver(new ReportableObserver() %7B%0D%0A            @Override%0D%0A            public void addNewReportable(Reportable reportable) %7B%0D%0A              try %7B%0D%0A                Thread.sleep(1);%0D%0A              %7D catch (InterruptedException e) %7B%0D%0A                Thread.interrupted();%0D%0A              %7D%0D%0A            %7D%0D%0A          %7D);%0D%0A      %7D catch (RuntimeException e) %7B%0D%0A        e.printStackTrace();%0D%0A      %7D%0D%0A    %7D%0D%0A%0D%0A  %7D%0D%0A%0D%0A  private class TimerJob extends Job %7B%0D%0A    @Override%0D%0A    protected void doJob() %7B%0D%0A      try %7B%0D%0A        String key = %22t%22 + rnd.nextInt(100000);%0D%0A        InApplicationMonitor.getInstance().addTimerMeasurement(key, 1);%0D%0A      %7D catch (RuntimeException e) %7B%0D%0A        e.printStackTrace();%0D%0A      %7D%0D%0A    %7D%0D%0A%0D%0A  %7D%0D%0A%7D%0D%0A

add test to check concurrency