@Disabled // a bit of manual testing of a Striped Semaphore
@Test
void testStripedSemaphore() throws InterruptedException {

    final List<String> keys = Arrays.asList(
            "one",
            "two",
            "three",
            "four");
    final Map<String, AtomicInteger> map = keys.stream()
            .map(k ->
                    Tuple.of(k, new AtomicInteger())
            )
            .collect(Collectors.toMap(Tuple2::_1, Tuple2::_2));
    final Striped<Semaphore> stripedSemaphore = Striped.semaphore(10, 1);
    final ExecutorService executorService = Executors.newFixedThreadPool(6);
    IntStream.rangeClosed(1, 1000000)
            .forEach(i -> {
                executorService.submit(() -> {
                    String key = keys.get(new Random().nextInt(keys.size()));
                    LOGGER.debug("Using key {} on thread {}", key, Thread.currentThread().getName());
                    Semaphore semaphore = stripedSemaphore.get(key);
                    try {
                        try {
                            semaphore.acquire();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        AtomicInteger atomicInteger = map.get(key);
                        boolean success = atomicInteger.compareAndSet(0, 1);
                        if (!success) {
                            throw new RuntimeException("compare and set failed");
                        }
                        ThreadUtil.sleepAtLeastIgnoreInterrupts(500);
                        success = atomicInteger.compareAndSet(1, 0);
                        if (!success) {
                            throw new RuntimeException("compare and set failed");
                        }
                    } finally {
                        semaphore.release();
                    }
                });
            });
    executorService.awaitTermination(20, TimeUnit.SECONDS);
}