From 966d2ea30fb5e895b3c4b242db037e8b395cb814 Mon Sep 17 00:00:00 2001 From: Tomasz Lelek Date: Thu, 27 Apr 2017 13:26:42 +0200 Subject: [PATCH] Bael 850 (#1732) * BAEL-786 Updated custom test reports * BAEL-850 ConcurentskipLIst * BAEL-850 formatting * BAEL-856 code for long adder and accumulator (#1723) * BAEL-856 code for long adder and accumulator * BAEL-856 rearange packages * BAEL-856 Formatting * BAEL-742 Create README for Stripe API article (#1731) * Add files via upload * Update pom.xml * Update RunGuice.java * Update Communication.java * Update CommunicationMode.java * Update DefaultCommunicator.java * Update EmailCommunicationMode.java * Update IMCommunicationMode.java * Update SMSCommunicationMode.java * Update MessageLogger.java * Update MessageSentLoggable.java * Update AOPModule.java * Update BasicModule.java * Update CommunicationModel.java * Update Communicator.java * Update BasicModule.java * Update RunGuice.java * Update MessageLogger.java * Update Communicator.java * Update pom.xml * BAEL-278: Updated README.md * BAEL-554: Add and update README.md files * Update pom.xml * Update pom.xml * Update pom.xml * BAEL-345: fixed assertion * BAEL-109: Updated README.md * BAEL-345: Added README.md * Reinstating reactor-core module in root-level pom * BAEL-393: Adding guide-intro module to root pom * BAEL-9: Updated README.md * BAEL-157: README.md updated * Changed project name * Update RunGuice.java Removed references to message logging and output * Update Communication.java Removed message logging-related code * BAEL-566: Updated README.md * New project name * BAEL-393: removing guice-intro directory * BAEL-393: renamed module guice-intro to guice in root pom.xml * BAEL-393 and BAEL-541 README.md files * BAEL-731: Updated README.md * BAEL-680: renamed test methods * BAEL-714: Updated README.md * BAEL-737: Updated README.md * BAEL-680 and BAEL-756 README.md updates * BAEL-666: Updated README * BAEL-415: Custom Scope * BAEL-415: Custom Scope - renamed classes to reflect TenantScope * README file updates for BAEL-723, BAEL-763, and BAEL-415 * BAEL-735: README * BAEL-567: README * BAEL-736: README * BAEL-766: Update README * BAEL-555: README update * BAEL-761: README update * BAEL-742: Stripe API for Java README file * Merge aspectj -> spring-aop (#1737) * BAEL-88 Integration tests fixed. (#1739) * BAEL-88 Testing in Spring Boot * BAEL-88 Integration tests fixed. * Merge assertj -> testing (#1738) * Guide to JDO (#1736) * Guide to JDO * Guide to JDO * Guide to JDO * Guide To JDO * BAEL-86: Corrected URL in README.md (#1740) * Add files via upload * Update pom.xml * Update RunGuice.java * Update Communication.java * Update CommunicationMode.java * Update DefaultCommunicator.java * Update EmailCommunicationMode.java * Update IMCommunicationMode.java * Update SMSCommunicationMode.java * Update MessageLogger.java * Update MessageSentLoggable.java * Update AOPModule.java * Update BasicModule.java * Update CommunicationModel.java * Update Communicator.java * Update BasicModule.java * Update RunGuice.java * Update MessageLogger.java * Update Communicator.java * Update pom.xml * BAEL-278: Updated README.md * BAEL-554: Add and update README.md files * Update pom.xml * Update pom.xml * Update pom.xml * BAEL-345: fixed assertion * BAEL-109: Updated README.md * BAEL-345: Added README.md * Reinstating reactor-core module in root-level pom * BAEL-393: Adding guide-intro module to root pom * BAEL-9: Updated README.md * BAEL-157: README.md updated * Changed project name * Update RunGuice.java Removed references to message logging and output * Update Communication.java Removed message logging-related code * BAEL-566: Updated README.md * New project name * BAEL-393: removing guice-intro directory * BAEL-393: renamed module guice-intro to guice in root pom.xml * BAEL-393 and BAEL-541 README.md files * BAEL-731: Updated README.md * BAEL-680: renamed test methods * BAEL-714: Updated README.md * BAEL-737: Updated README.md * BAEL-680 and BAEL-756 README.md updates * BAEL-666: Updated README * BAEL-415: Custom Scope * BAEL-415: Custom Scope - renamed classes to reflect TenantScope * README file updates for BAEL-723, BAEL-763, and BAEL-415 * BAEL-735: README * BAEL-567: README * BAEL-736: README * BAEL-766: Update README * BAEL-555: README update * BAEL-761: README update * BAEL-742: Stripe API for Java README file * BAEL-86: Correction to README file * BAEL-850 Formatting --- .../baeldung/concurrent/skiplist/Event.java | 21 +++ .../concurrent/skiplist/EventWindowSort.java | 36 ++++++ .../skiplist/ConcurrentSkipListSetTest.java | 120 ++++++++++++++++++ 3 files changed, 177 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/concurrent/skiplist/Event.java create mode 100644 core-java/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java create mode 100644 core-java/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetTest.java diff --git a/core-java/src/main/java/com/baeldung/concurrent/skiplist/Event.java b/core-java/src/main/java/com/baeldung/concurrent/skiplist/Event.java new file mode 100644 index 0000000000..ce1f57bb93 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/skiplist/Event.java @@ -0,0 +1,21 @@ +package com.baeldung.concurrent.skiplist; + +import java.time.ZonedDateTime; + +public class Event { + private final ZonedDateTime eventTime; + private final String content; + + public Event(ZonedDateTime eventTime, String content) { + this.eventTime = eventTime; + this.content = content; + } + + public ZonedDateTime getEventTime() { + return eventTime; + } + + public String getContent() { + return content; + } +} diff --git a/core-java/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java b/core-java/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java new file mode 100644 index 0000000000..9eef00bd3f --- /dev/null +++ b/core-java/src/main/java/com/baeldung/concurrent/skiplist/EventWindowSort.java @@ -0,0 +1,36 @@ +package com.baeldung.concurrent.skiplist; + +import java.time.ZonedDateTime; +import java.util.Comparator; +import java.util.concurrent.ConcurrentNavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.function.ToLongFunction; + +public class EventWindowSort { + private final ConcurrentSkipListMap events = new ConcurrentSkipListMap<>(Comparator.comparingLong(new ToLongFunction() { + @Override + public long applyAsLong(ZonedDateTime value) { + return value + .toInstant() + .toEpochMilli(); + } + })); + + public void acceptEvent(Event event) { + events.put(event.getEventTime(), event.getContent()); + } + + public ConcurrentNavigableMap getEventsFromLastMinute() { + return events.tailMap(ZonedDateTime + .now() + .minusMinutes(1)); + } + + public ConcurrentNavigableMap getEventsOlderThatOneMinute() { + return events.headMap(ZonedDateTime + .now() + .minusMinutes(1)); + } + +} + diff --git a/core-java/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetTest.java b/core-java/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetTest.java new file mode 100644 index 0000000000..a2dbbae520 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/concurrent/skiplist/ConcurrentSkipListSetTest.java @@ -0,0 +1,120 @@ +package com.baeldung.concurrent.skiplist; + +import org.junit.Test; + +import java.time.ZonedDateTime; +import java.util.UUID; +import java.util.concurrent.ConcurrentNavigableMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class ConcurrentSkipListSetTest { + + @Test + public void givenThreadsProducingEvents_whenGetForEventsFromLastMinute_thenReturnThoseEventsInTheLockFreeWay() throws InterruptedException { + //given + ExecutorService executorService = Executors.newFixedThreadPool(3); + EventWindowSort eventWindowSort = new EventWindowSort(); + int numberOfThreads = 2; + //when + Runnable producer = () -> IntStream + .rangeClosed(0, 100) + .forEach(index -> eventWindowSort.acceptEvent(new Event(ZonedDateTime + .now() + .minusSeconds(index), UUID + .randomUUID() + .toString()))); + + for (int i = 0; i < numberOfThreads; i++) { + executorService.execute(producer); + } + + Thread.sleep(500); + + ConcurrentNavigableMap eventsFromLastMinute = eventWindowSort.getEventsFromLastMinute(); + + long eventsOlderThanOneMinute = eventsFromLastMinute + .entrySet() + .stream() + .filter(e -> e + .getKey() + .isBefore(ZonedDateTime + .now() + .minusMinutes(1))) + .count(); + assertEquals(eventsOlderThanOneMinute, 0); + + long eventYoungerThanOneMinute = eventsFromLastMinute + .entrySet() + .stream() + .filter(e -> e + .getKey() + .isAfter(ZonedDateTime + .now() + .minusMinutes(1))) + .count(); + + //then + assertTrue(eventYoungerThanOneMinute > 0); + + executorService.awaitTermination(1, TimeUnit.SECONDS); + executorService.shutdown(); + } + + @Test + public void givenThreadsProducingEvents_whenGetForEventsOlderThanOneMinute_thenReturnThoseEventsInTheLockFreeWay() throws InterruptedException { + //given + ExecutorService executorService = Executors.newFixedThreadPool(3); + EventWindowSort eventWindowSort = new EventWindowSort(); + int numberOfThreads = 2; + //when + Runnable producer = () -> IntStream + .rangeClosed(0, 100) + .forEach(index -> eventWindowSort.acceptEvent(new Event(ZonedDateTime + .now() + .minusSeconds(index), UUID + .randomUUID() + .toString()))); + + for (int i = 0; i < numberOfThreads; i++) { + executorService.execute(producer); + } + + Thread.sleep(500); + + ConcurrentNavigableMap eventsFromLastMinute = eventWindowSort.getEventsOlderThatOneMinute(); + + long eventsOlderThanOneMinute = eventsFromLastMinute + .entrySet() + .stream() + .filter(e -> e + .getKey() + .isBefore(ZonedDateTime + .now() + .minusMinutes(1))) + .count(); + assertTrue(eventsOlderThanOneMinute > 0); + + long eventYoungerThanOneMinute = eventsFromLastMinute + .entrySet() + .stream() + .filter(e -> e + .getKey() + .isAfter(ZonedDateTime + .now() + .minusMinutes(1))) + .count(); + + //then + assertEquals(eventYoungerThanOneMinute, 0); + + executorService.awaitTermination(1, TimeUnit.SECONDS); + executorService.shutdown(); + } + +} \ No newline at end of file