BAEL-3139: Moved code to a new project core-java-concurrency-2 (#7778)
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.concurrent.mutex;
|
||||
|
||||
public class SequenceGenerator {
|
||||
|
||||
private int currentValue = 0;
|
||||
|
||||
public int getNextSequence() {
|
||||
currentValue = currentValue + 1;
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.concurrent.mutex;
|
||||
|
||||
import com.google.common.util.concurrent.Monitor;
|
||||
|
||||
public class SequenceGeneratorUsingMonitor extends SequenceGenerator {
|
||||
|
||||
private Monitor mutex = new Monitor();
|
||||
|
||||
@Override
|
||||
public int getNextSequence() {
|
||||
mutex.enter();
|
||||
try {
|
||||
return super.getNextSequence();
|
||||
} finally {
|
||||
mutex.leave();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.concurrent.mutex;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class SequenceGeneratorUsingReentrantLock extends SequenceGenerator {
|
||||
|
||||
private ReentrantLock mutex = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
public int getNextSequence() {
|
||||
try {
|
||||
mutex.lock();
|
||||
return super.getNextSequence();
|
||||
} finally {
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.concurrent.mutex;
|
||||
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
public class SequenceGeneratorUsingSemaphore extends SequenceGenerator {
|
||||
|
||||
private Semaphore mutex = new Semaphore(1);
|
||||
|
||||
@Override
|
||||
public int getNextSequence() {
|
||||
try {
|
||||
mutex.acquire();
|
||||
return super.getNextSequence();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Exception in critical section.", e);
|
||||
} finally {
|
||||
mutex.release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.concurrent.mutex;
|
||||
|
||||
public class SequenceGeneratorUsingSynchronizedBlock extends SequenceGenerator {
|
||||
|
||||
private Object mutex = new Object();
|
||||
|
||||
@Override
|
||||
public int getNextSequence() {
|
||||
synchronized (mutex) {
|
||||
return super.getNextSequence();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.baeldung.concurrent.mutex;
|
||||
|
||||
public class SequenceGeneratorUsingSynchronizedMethod extends SequenceGenerator {
|
||||
|
||||
@Override
|
||||
public synchronized int getNextSequence() {
|
||||
return super.getNextSequence();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework" level="WARN" />
|
||||
<logger name="org.springframework.transaction" level="WARN" />
|
||||
|
||||
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
|
||||
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.baeldung.concurrent.mutex;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MutexUnitTest {
|
||||
|
||||
// @Test
|
||||
// This test verifies the race condition use case, it may pass or fail based on execution environment
|
||||
// Uncomment @Test to run it
|
||||
public void givenUnsafeSequenceGenerator_whenRaceCondition_thenUnexpectedBehavior() throws Exception {
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGenerator(), count);
|
||||
Assert.assertNotEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingSynchronizedMethod_whenRaceCondition_thenSuccess() throws Exception {
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSynchronizedMethod(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingSynchronizedBlock_whenRaceCondition_thenSuccess() throws Exception {
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSynchronizedBlock(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingReentrantLock_whenRaceCondition_thenSuccess() throws Exception {
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingReentrantLock(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingSemaphore_whenRaceCondition_thenSuccess() throws Exception {
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSemaphore(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingMonitor_whenRaceCondition_thenSuccess() throws Exception {
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingMonitor(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
private Set<Integer> getUniqueSequences(SequenceGenerator generator, int count) throws Exception {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(3);
|
||||
Set<Integer> uniqueSequences = new LinkedHashSet<>();
|
||||
List<Future<Integer>> futures = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
futures.add(executor.submit(generator::getNextSequence));
|
||||
}
|
||||
|
||||
for (Future<Integer> future : futures) {
|
||||
uniqueSequences.add(future.get());
|
||||
}
|
||||
|
||||
executor.awaitTermination(1, TimeUnit.SECONDS);
|
||||
executor.shutdown();
|
||||
|
||||
return uniqueSequences;
|
||||
}
|
||||
|
||||
}
|
||||
13
core-java-modules/core-java-concurrency-2/src/test/resources/.gitignore
vendored
Normal file
13
core-java-modules/core-java-concurrency-2/src/test/resources/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
*.class
|
||||
|
||||
#folders#
|
||||
/target
|
||||
/neoDb*
|
||||
/data
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
Reference in New Issue
Block a user