JVMUtil { public static <T> List<Throwable> repeatConcurrently(final int threads, final int totalIterationsCount, final Function<Integer, Object> task) { final AtomicInteger atomicLong = new AtomicInteger( totalIterationsCount ); final CountDownLatch countDownLatch = new CountDownLatch( threads ); final LinkedList<Throwable> errors = Lists.newLinkedList(); for ( int j = 0; j < threads; j++ ) { Thread thread = new Thread( new Runnable() { @Override public void run() { try { int l; while ( ( l = atomicLong.decrementAndGet() ) >= 0 ) try { task.apply( l ); } catch ( Throwable e ) { Log.error( e.getMessage(), e ); errors.add( e ); Throwables.propagate( e ); } } finally { countDownLatch.countDown(); } } } ); thread.setName( String.format( "RepeateConcurrentlyThread-%s:{%s}", j, task.toString() ) ); thread.start(); } Uninterruptibles.awaitUninterruptibly( countDownLatch ); return errors; } private  JVMUtil(); static void gc(); static void gcOnExit(); static Field fieldFor(final Class<?> clazz,
                                 final String name); @SuppressWarnings("unchecked") static T getPropertyValueUnsafe(final Object source,
                                               final Class<T> valueType,
                                               final long fieldOffset); static void setPropertyValueUnsafe(final Object source,
                                                  final T value,
                                                  final Class<T> valueType,
                                                  final long fieldOffset); static Exception runAndGetExecutionException(final Runnable runnable); static List<Throwable> repeatConcurrently(final int threads,
                                                         final int totalIterationsCount,
                                                         final Function<Integer, Object> task); static List<Throwable> repeatConcurrently(final int threads,
                                                         final int totalIterationsCount,
                                                         final Runnable task); static int murmurRehash(final int hash); static int jdkRehash(final int hash); static boolean equals(final Object o1,
                                 final Object o2); static void ensureEnoughMemoryCapacity(final ByteArrayPointer pointer,
                                                  final CapacityRestriction capacityRestriction,
                                                  final Sequence memoryUsed); static void ensureEnoughCapacity(final Object obj,
                                            final CapacityRestriction capacityRestriction,
                                            final Sequence itemsCount);  }
@Test public void repeateConcurrentlyWorks() { final AtomicInteger integer = new AtomicInteger(); JVMUtil.repeatConcurrently( 2, 5, new Function<Integer, Object>() { @Override public Object apply(final Integer input) { integer.incrementAndGet(); return this; } } ); assertThat( integer.get(), is( 5 ) ); }
@Test public void canGetExceptionsConcurenly() { assertThat( JVMUtil.repeatConcurrently( Runtime.getRuntime().availableProcessors(), 100, new Runnable() { AtomicInteger counter = new AtomicInteger(); @Override public void run() { if ( counter.incrementAndGet() % 2 == 0 ) throw new IllegalStateException( "exception" ); } } ).size(), is( greaterThan( 0 ) ) ); }