Merge branch 'master' of https://github.com/eugenp/tutorials into BAEL-16822
This commit is contained in:
commit
88b03226de
|
@ -1,11 +1,12 @@
|
|||
package com.baeldung.concurrent.mutex;
|
||||
|
||||
public class SequenceGenerator {
|
||||
|
||||
private int currentValue = 0;
|
||||
|
||||
public int getNextSequence() throws InterruptedException {
|
||||
public int getNextSequence() {
|
||||
currentValue = currentValue + 1;
|
||||
Thread.sleep(500);
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,15 +4,16 @@ import com.google.common.util.concurrent.Monitor;
|
|||
|
||||
public class SequenceGeneratorUsingMonitor extends SequenceGenerator {
|
||||
|
||||
private Monitor monitor = new Monitor();
|
||||
private Monitor mutex = new Monitor();
|
||||
|
||||
@Override
|
||||
public int getNextSequence() throws InterruptedException {
|
||||
monitor.enter();
|
||||
public int getNextSequence() {
|
||||
mutex.enter();
|
||||
try {
|
||||
return super.getNextSequence();
|
||||
} finally {
|
||||
monitor.leave();
|
||||
mutex.leave();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ public class SequenceGeneratorUsingReentrantLock extends SequenceGenerator {
|
|||
private ReentrantLock mutex = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
public int getNextSequence() throws InterruptedException {
|
||||
public int getNextSequence() {
|
||||
try {
|
||||
mutex.lock();
|
||||
return super.getNextSequence();
|
||||
|
@ -15,4 +15,5 @@ public class SequenceGeneratorUsingReentrantLock extends SequenceGenerator {
|
|||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,12 +7,15 @@ public class SequenceGeneratorUsingSemaphore extends SequenceGenerator {
|
|||
private Semaphore mutex = new Semaphore(1);
|
||||
|
||||
@Override
|
||||
public int getNextSequence() throws InterruptedException {
|
||||
public int getNextSequence() {
|
||||
try {
|
||||
mutex.acquire();
|
||||
return super.getNextSequence();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException("Exception in critical section.", e);
|
||||
} finally {
|
||||
mutex.release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@ package com.baeldung.concurrent.mutex;
|
|||
|
||||
public class SequenceGeneratorUsingSynchronizedBlock extends SequenceGenerator {
|
||||
|
||||
private Object mutex = new Object();
|
||||
|
||||
@Override
|
||||
public int getNextSequence() throws InterruptedException {
|
||||
synchronized (this) {
|
||||
public int getNextSequence() {
|
||||
synchronized (mutex) {
|
||||
return super.getNextSequence();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.baeldung.concurrent.mutex;
|
|||
public class SequenceGeneratorUsingSynchronizedMethod extends SequenceGenerator {
|
||||
|
||||
@Override
|
||||
public synchronized int getNextSequence() throws InterruptedException {
|
||||
public synchronized int getNextSequence() {
|
||||
return super.getNextSequence();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.baeldung.concurrent.mutex;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
@ -12,59 +12,58 @@ import java.util.concurrent.TimeUnit;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.concurrent.mutex.SequenceGenerator;
|
||||
import com.baeldung.concurrent.mutex.SequenceGeneratorUsingMonitor;
|
||||
import com.baeldung.concurrent.mutex.SequenceGeneratorUsingReentrantLock;
|
||||
import com.baeldung.concurrent.mutex.SequenceGeneratorUsingSemaphore;
|
||||
import com.baeldung.concurrent.mutex.SequenceGeneratorUsingSynchronizedBlock;
|
||||
import com.baeldung.concurrent.mutex.SequenceGeneratorUsingSynchronizedMethod;
|
||||
|
||||
public class MutexUnitTest {
|
||||
|
||||
private final int RANGE = 30;
|
||||
|
||||
@Test
|
||||
// @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 {
|
||||
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGenerator());
|
||||
Assert.assertNotEquals(RANGE, uniqueSequences.size());
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGenerator(), count);
|
||||
Assert.assertNotEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingSynchronizedMethod_whenRaceCondition_thenSuccess() throws Exception {
|
||||
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSynchronizedMethod());
|
||||
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSynchronizedMethod(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingSynchronizedBlock_whenRaceCondition_thenSuccess() throws Exception {
|
||||
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSynchronizedBlock());
|
||||
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSynchronizedBlock(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingReentrantLock_whenRaceCondition_thenSuccess() throws Exception {
|
||||
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingReentrantLock());
|
||||
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingReentrantLock(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingSemaphore_whenRaceCondition_thenSuccess() throws Exception {
|
||||
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSemaphore());
|
||||
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSemaphore(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSequenceGeneratorUsingMonitor_whenRaceCondition_thenSuccess() throws Exception {
|
||||
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingMonitor());
|
||||
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||
int count = 1000;
|
||||
Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingMonitor(), count);
|
||||
Assert.assertEquals(count, uniqueSequences.size());
|
||||
}
|
||||
|
||||
private Set<Integer> getASetOFUniqueSequences(SequenceGenerator generator) throws Exception {
|
||||
private Set<Integer> getUniqueSequences(SequenceGenerator generator, int count) throws Exception {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(3);
|
||||
Set<Integer> uniqueSequences = new HashSet<>();
|
||||
Set<Integer> uniqueSequences = new LinkedHashSet<>();
|
||||
List<Future<Integer>> futures = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < RANGE; i++) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
futures.add(executor.submit(generator::getNextSequence));
|
||||
}
|
||||
|
||||
|
@ -72,7 +71,7 @@ public class MutexUnitTest {
|
|||
uniqueSequences.add(future.get());
|
||||
}
|
||||
|
||||
executor.awaitTermination(15, TimeUnit.SECONDS);
|
||||
executor.awaitTermination(1, TimeUnit.SECONDS);
|
||||
executor.shutdown();
|
||||
|
||||
return uniqueSequences;
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package com.baeldung.core.modifiers;
|
||||
|
||||
public class Employee {
|
||||
|
||||
private String privateId;
|
||||
public String name;
|
||||
private boolean manager;
|
||||
|
||||
public Employee(String id, String name) {
|
||||
changeId(id);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private Employee(String id, String name, boolean managerAttribute) {
|
||||
this.privateId = id;
|
||||
this.name = name;
|
||||
this.privateId = id + "_ID-MANAGER";
|
||||
}
|
||||
|
||||
public void changeId(String customId) {
|
||||
if (customId.endsWith("_ID")) {
|
||||
this.privateId = customId;
|
||||
} else {
|
||||
this.privateId = customId + "_ID";
|
||||
}
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return privateId;
|
||||
}
|
||||
|
||||
public boolean isManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
public void elevateToManager() {
|
||||
if ("Carl".equals(this.name)) {
|
||||
setManager(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void setManager(boolean manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public static Employee buildManager(String id, String name) {
|
||||
return new Employee(id, name, true);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.core.modifiers;
|
||||
|
||||
public class ExampleClass {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Employee employee = new Employee("Bob","ABC123");
|
||||
employee.changeId("BCD234");
|
||||
System.out.println(employee.getId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.core.modifiers;
|
||||
|
||||
public class PublicOuterClass {
|
||||
|
||||
public PrivateInnerClass getInnerClassInstance() {
|
||||
PrivateInnerClass myPrivateClassInstance = this.new PrivateInnerClass();
|
||||
myPrivateClassInstance.id = "ID1";
|
||||
myPrivateClassInstance.name = "Bob";
|
||||
return myPrivateClassInstance;
|
||||
}
|
||||
|
||||
private class PrivateInnerClass {
|
||||
public String name;
|
||||
public String id;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue