BAEL 1639: added singleton examples and test. (#3977)
This commit is contained in:
parent
5b5386636b
commit
5f83980363
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.designpatterns.singleton.synchronization;
|
||||
|
||||
/**
|
||||
* Double-checked locking design pattern applied to a singleton.
|
||||
*
|
||||
* @author Donato Rimenti
|
||||
*
|
||||
*/
|
||||
public class DclSingleton {
|
||||
|
||||
/**
|
||||
* Current instance of the singleton.
|
||||
*/
|
||||
private static volatile DclSingleton instance;
|
||||
|
||||
/**
|
||||
* Private constructor to avoid instantiation.
|
||||
*/
|
||||
private DclSingleton() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current instance of the singleton.
|
||||
*
|
||||
* @return the current instance of the singleton
|
||||
*/
|
||||
public static DclSingleton getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (DclSingleton.class) {
|
||||
if (instance == null) {
|
||||
instance = new DclSingleton();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.designpatterns.singleton.synchronization;
|
||||
|
||||
/**
|
||||
* Draconian singleton. The method to get the instance is synchronized.
|
||||
*
|
||||
* @author Donato Rimenti
|
||||
*
|
||||
*/
|
||||
public class DraconianSingleton {
|
||||
|
||||
/**
|
||||
* Current instance of the singleton.
|
||||
*/
|
||||
private static DraconianSingleton instance;
|
||||
|
||||
/**
|
||||
* Private constructor to avoid instantiation.
|
||||
*/
|
||||
private DraconianSingleton() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current instance of the singleton.
|
||||
*
|
||||
* @return the current instance of the singleton
|
||||
*/
|
||||
public static synchronized DraconianSingleton getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new DraconianSingleton();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.baeldung.designpatterns.singleton.synchronization;
|
||||
|
||||
/**
|
||||
* Singleton with early initialization. Inlines the singleton instance
|
||||
* initialization.
|
||||
*
|
||||
* @author Donato Rimenti
|
||||
*
|
||||
*/
|
||||
public class EarlyInitSingleton {
|
||||
|
||||
/**
|
||||
* Current instance of the singleton.
|
||||
*/
|
||||
private static final EarlyInitSingleton INSTANCE = new EarlyInitSingleton();
|
||||
|
||||
/**
|
||||
* Private constructor to avoid instantiation.
|
||||
*/
|
||||
private EarlyInitSingleton() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current instance of the singleton.
|
||||
*
|
||||
* @return the current instance of the singleton
|
||||
*/
|
||||
public static EarlyInitSingleton getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.designpatterns.singleton.synchronization;
|
||||
|
||||
/**
|
||||
* Enum singleton pattern. Uses an enum to hold a reference to the singleton
|
||||
* instance.
|
||||
*
|
||||
* @author Donato Rimenti
|
||||
*
|
||||
*/
|
||||
public enum EnumSingleton {
|
||||
|
||||
/**
|
||||
* Current instance of the singleton.
|
||||
*/
|
||||
INSTANCE;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.designpatterns.singleton.synchronization;
|
||||
|
||||
/**
|
||||
* Initialization on demand singleton pattern. Uses a nested static class to
|
||||
* hold a reference to the singleton instance.
|
||||
*
|
||||
* @author Donato Rimenti
|
||||
*
|
||||
*/
|
||||
public class InitOnDemandSingleton {
|
||||
|
||||
/**
|
||||
* Holder for a singleton instance.
|
||||
*
|
||||
* @author Donato Rimenti
|
||||
*
|
||||
*/
|
||||
private static class InstanceHolder {
|
||||
|
||||
/**
|
||||
* Current instance of the singleton.
|
||||
*/
|
||||
private static final InitOnDemandSingleton INSTANCE = new InitOnDemandSingleton();
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to avoid instantiation.
|
||||
*/
|
||||
private InitOnDemandSingleton() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current instance of the singleton.
|
||||
*
|
||||
* @return the current instance of the singleton
|
||||
*/
|
||||
public static InitOnDemandSingleton getInstance() {
|
||||
return InstanceHolder.INSTANCE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package com.baeldung.designpatterns.singleton.synchronization;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for the singleton synchronization package with the same name.
|
||||
*
|
||||
* @author Donato Rimenti
|
||||
*
|
||||
*/
|
||||
public class SingletonSynchronizationUnitTest {
|
||||
|
||||
/**
|
||||
* Size of the thread pools used.
|
||||
*/
|
||||
private static final int POOL_SIZE = 1_000;
|
||||
|
||||
/**
|
||||
* Number of tasks to submit.
|
||||
*/
|
||||
private static final int TASKS_TO_SUBMIT = 1_000_000;
|
||||
|
||||
/**
|
||||
* Tests the thread-safety of {@link DraconianSingleton}.
|
||||
*/
|
||||
@Test
|
||||
public void givenDraconianSingleton_whenMultithreadInstancesEquals_thenTrue() {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);
|
||||
Set<DraconianSingleton> resultSet = Collections.synchronizedSet(new HashSet<DraconianSingleton>());
|
||||
|
||||
// Submits the instantiation tasks.
|
||||
for (int i = 0; i < TASKS_TO_SUBMIT; i++) {
|
||||
executor.submit(() -> resultSet.add(DraconianSingleton.getInstance()));
|
||||
}
|
||||
|
||||
// Since the instance of the object we inserted into the set is always
|
||||
// the same, the size should be one.
|
||||
Assert.assertEquals(1, resultSet.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the thread-safety of {@link DclSingleton}.
|
||||
*/
|
||||
@Test
|
||||
public void givenDclSingleton_whenMultithreadInstancesEquals_thenTrue() {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);
|
||||
Set<DclSingleton> resultSet = Collections.synchronizedSet(new HashSet<DclSingleton>());
|
||||
|
||||
// Submits the instantiation tasks.
|
||||
for (int i = 0; i < TASKS_TO_SUBMIT; i++) {
|
||||
executor.submit(() -> resultSet.add(DclSingleton.getInstance()));
|
||||
}
|
||||
|
||||
// Since the instance of the object we inserted into the set is always
|
||||
// the same, the size should be one.
|
||||
Assert.assertEquals(1, resultSet.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the thread-safety of {@link EarlyInitSingleton}.
|
||||
*/
|
||||
@Test
|
||||
public void givenEarlyInitSingleton_whenMultithreadInstancesEquals_thenTrue() {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);
|
||||
Set<EarlyInitSingleton> resultSet = Collections.synchronizedSet(new HashSet<EarlyInitSingleton>());
|
||||
|
||||
// Submits the instantiation tasks.
|
||||
for (int i = 0; i < TASKS_TO_SUBMIT; i++) {
|
||||
executor.submit(() -> resultSet.add(EarlyInitSingleton.getInstance()));
|
||||
}
|
||||
|
||||
// Since the instance of the object we inserted into the set is always
|
||||
// the same, the size should be one.
|
||||
Assert.assertEquals(1, resultSet.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the thread-safety of {@link InitOnDemandSingleton}.
|
||||
*/
|
||||
@Test
|
||||
public void givenInitOnDemandSingleton_whenMultithreadInstancesEquals_thenTrue() {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);
|
||||
Set<InitOnDemandSingleton> resultSet = Collections.synchronizedSet(new HashSet<InitOnDemandSingleton>());
|
||||
|
||||
// Submits the instantiation tasks.
|
||||
for (int i = 0; i < TASKS_TO_SUBMIT; i++) {
|
||||
executor.submit(() -> resultSet.add(InitOnDemandSingleton.getInstance()));
|
||||
}
|
||||
|
||||
// Since the instance of the object we inserted into the set is always
|
||||
// the same, the size should be one.
|
||||
Assert.assertEquals(1, resultSet.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the thread-safety of {@link EnumSingleton}.
|
||||
*/
|
||||
@Test
|
||||
public void givenEnumSingleton_whenMultithreadInstancesEquals_thenTrue() {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);
|
||||
Set<EnumSingleton> resultSet = Collections.synchronizedSet(new HashSet<EnumSingleton>());
|
||||
|
||||
// Submits the instantiation tasks.
|
||||
for (int i = 0; i < TASKS_TO_SUBMIT; i++) {
|
||||
executor.submit(() -> resultSet.add(EnumSingleton.INSTANCE));
|
||||
}
|
||||
|
||||
// Since the instance of the object we inserted into the set is always
|
||||
// the same, the size should be one.
|
||||
Assert.assertEquals(1, resultSet.size());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue