mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-18 21:25:52 +00:00
deps: Refactor dependencies (#3224)
* remove spring dep move junit, logging, mockito under dep mgmt * upgrade anti-corruption-layer deps * async method invocation * balking, bloc * bridge to bytecode * caching * callback - cqrs * component - health check * hexagonal - metadata mapping * rest of the patterns * remove checkstyle, take spotless into use
This commit is contained in:
@@ -27,39 +27,40 @@ package com.iluwatar.singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* <p>Singleton pattern ensures that the class can have only one existing instance per Java
|
||||
* classloader instance and provides global access to it.</p>
|
||||
* Singleton pattern ensures that the class can have only one existing instance per Java classloader
|
||||
* instance and provides global access to it.
|
||||
*
|
||||
* <p>One of the risks of this pattern is that bugs resulting from setting a singleton up in a
|
||||
* distributed environment can be tricky to debug since it will work fine if you debug with a
|
||||
* single classloader. Additionally, these problems can crop up a while after the implementation of
|
||||
* a singleton, since they may start synchronous and only become async with time, so it may
|
||||
* not be clear why you are seeing certain changes in behavior.</p>
|
||||
* distributed environment can be tricky to debug since it will work fine if you debug with a single
|
||||
* classloader. Additionally, these problems can crop up a while after the implementation of a
|
||||
* singleton, since they may start synchronous and only become async with time, so it may not be
|
||||
* clear why you are seeing certain changes in behavior.
|
||||
*
|
||||
* <p>There are many ways to implement the Singleton. The first one is the eagerly initialized
|
||||
* instance in {@link IvoryTower}. Eager initialization implies that the implementation is thread
|
||||
* safe. If you can afford to give up control of the instantiation moment, then this implementation
|
||||
* will suit you fine.</p>
|
||||
* will suit you fine.
|
||||
*
|
||||
* <p>The other option to implement eagerly initialized Singleton is enum-based Singleton. The
|
||||
* example is found in {@link EnumIvoryTower}. At first glance, the code looks short and simple.
|
||||
* However, you should be aware of the downsides including committing to implementation strategy,
|
||||
* extending the enum class, serializability, and restrictions to coding. These are extensively
|
||||
* discussed in Stack Overflow: http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
|
||||
* -a-singleton-with-javas-enum</p>
|
||||
* discussed in Stack Overflow:
|
||||
* http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing
|
||||
* -a-singleton-with-javas-enum
|
||||
*
|
||||
* <p>{@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on
|
||||
* demand. The downside is that it is very slow to access since the whole access method is
|
||||
* synchronized.</p>
|
||||
* synchronized.
|
||||
*
|
||||
* <p>Another Singleton implementation that is initialized on demand is found in
|
||||
* {@link ThreadSafeDoubleCheckLocking}. It is somewhat faster than {@link
|
||||
* ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method but only the
|
||||
* method internals on specific conditions.</p>
|
||||
* <p>Another Singleton implementation that is initialized on demand is found in {@link
|
||||
* ThreadSafeDoubleCheckLocking}. It is somewhat faster than {@link ThreadSafeLazyLoadedIvoryTower}
|
||||
* since it doesn't synchronize the whole access method but only the method internals on specific
|
||||
* conditions.
|
||||
*
|
||||
* <p>Yet another way to implement thread-safe lazily initialized Singleton can be found in
|
||||
* {@link InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8
|
||||
* API level to work.</p>
|
||||
* <p>Yet another way to implement thread-safe lazily initialized Singleton can be found in {@link
|
||||
* InitializingOnDemandHolderIdiom}. However, this implementation requires at least Java 8 API level
|
||||
* to work.
|
||||
*/
|
||||
@Slf4j
|
||||
public class App {
|
||||
|
||||
@@ -25,20 +25,16 @@
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* <p>Bill Pugh Singleton Implementation.</p>
|
||||
*
|
||||
* <p>This implementation of the singleton design pattern takes advantage of the
|
||||
* Java memory model's guarantees about class initialization. Each class is
|
||||
* initialized only once, when it is first used. If the class hasn't been used
|
||||
* yet, it won't be loaded into memory, and no memory will be allocated for
|
||||
* a static instance. This makes the singleton instance lazy-loaded and thread-safe.</p>
|
||||
* Bill Pugh Singleton Implementation.
|
||||
*
|
||||
* <p>This implementation of the singleton design pattern takes advantage of the Java memory model's
|
||||
* guarantees about class initialization. Each class is initialized only once, when it is first
|
||||
* used. If the class hasn't been used yet, it won't be loaded into memory, and no memory will be
|
||||
* allocated for a static instance. This makes the singleton instance lazy-loaded and thread-safe.
|
||||
*/
|
||||
public final class BillPughImplementation {
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation from outside the class.
|
||||
*/
|
||||
/** Private constructor to prevent instantiation from outside the class. */
|
||||
private BillPughImplementation() {
|
||||
// to prevent instantiating by Reflection call
|
||||
if (InstanceHolder.instance != null) {
|
||||
@@ -47,24 +43,19 @@ public final class BillPughImplementation {
|
||||
}
|
||||
|
||||
/**
|
||||
* The InstanceHolder is a static inner class, and it holds the Singleton instance.
|
||||
* It is not loaded into memory until the getInstance() method is called.
|
||||
* The InstanceHolder is a static inner class, and it holds the Singleton instance. It is not
|
||||
* loaded into memory until the getInstance() method is called.
|
||||
*/
|
||||
private static class InstanceHolder {
|
||||
/**
|
||||
* Singleton instance of the class.
|
||||
*/
|
||||
/** Singleton instance of the class. */
|
||||
private static BillPughImplementation instance = new BillPughImplementation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Public accessor for the singleton instance.
|
||||
*
|
||||
* <p>
|
||||
* When this method is called, the InstanceHolder is loaded into memory
|
||||
* and creates the Singleton instance. This method provides a global access point
|
||||
* for the singleton instance.
|
||||
* </p>
|
||||
* <p>When this method is called, the InstanceHolder is loaded into memory and creates the
|
||||
* Singleton instance. This method provides a global access point for the singleton instance.
|
||||
*
|
||||
* @return an instance of the class.
|
||||
*/
|
||||
|
||||
@@ -25,16 +25,14 @@
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* <p>Enum based singleton implementation. Effective Java 2nd Edition (Joshua Bloch) p. 18</p>
|
||||
* Enum based singleton implementation. Effective Java 2nd Edition (Joshua Bloch) p. 18
|
||||
*
|
||||
* <p>This implementation is thread safe, however adding any other method and its thread safety
|
||||
* is developers responsibility.</p>
|
||||
* <p>This implementation is thread safe, however adding any other method and its thread safety is
|
||||
* developers responsibility.
|
||||
*/
|
||||
public enum EnumIvoryTower {
|
||||
|
||||
/**
|
||||
* The singleton instance of the class, created by the Java enum singleton pattern.
|
||||
*/
|
||||
/** The singleton instance of the class, created by the Java enum singleton pattern. */
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
|
||||
+8
-15
@@ -25,23 +25,20 @@
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* <p>The Initialize-on-demand-holder idiom is a secure way of creating a lazy initialized singleton
|
||||
* object in Java.</p>
|
||||
* The Initialize-on-demand-holder idiom is a secure way of creating a lazy initialized singleton
|
||||
* object in Java.
|
||||
*
|
||||
* <p>The technique is as lazy as possible and works in all known versions of Java. It takes
|
||||
* advantage of language guarantees about class initialization, and will therefore work correctly
|
||||
* in all Java-compliant compilers and virtual machines.</p>
|
||||
* advantage of language guarantees about class initialization, and will therefore work correctly in
|
||||
* all Java-compliant compilers and virtual machines.
|
||||
*
|
||||
* <p>The inner class is referenced no earlier (and therefore loaded no earlier by the class loader)
|
||||
* than the moment that getInstance() is called. Thus, this solution is thread-safe without
|
||||
* requiring special language constructs (i.e. volatile or synchronized).</p>
|
||||
*
|
||||
* requiring special language constructs (i.e. volatile or synchronized).
|
||||
*/
|
||||
public final class InitializingOnDemandHolderIdiom {
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
*/
|
||||
/** Private constructor. */
|
||||
private InitializingOnDemandHolderIdiom() {
|
||||
// to prevent instantiating by Reflection call
|
||||
if (HelperHolder.INSTANCE != null) {
|
||||
@@ -58,14 +55,10 @@ public final class InitializingOnDemandHolderIdiom {
|
||||
return HelperHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the lazy-loaded Singleton instance.
|
||||
*/
|
||||
/** Provides the lazy-loaded Singleton instance. */
|
||||
private static class HelperHolder {
|
||||
|
||||
/**
|
||||
* Singleton instance of the class.
|
||||
*/
|
||||
/** Singleton instance of the class. */
|
||||
private static final InitializingOnDemandHolderIdiom INSTANCE =
|
||||
new InitializingOnDemandHolderIdiom();
|
||||
}
|
||||
|
||||
@@ -1,55 +1,49 @@
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* Singleton class. Eagerly initialized static instance guarantees thread safety.
|
||||
*/
|
||||
public final class IvoryTower {
|
||||
|
||||
/**
|
||||
* Private constructor so nobody can instantiate the class.
|
||||
*/
|
||||
private IvoryTower() {
|
||||
// to prevent instantiating by Reflection call
|
||||
if (INSTANCE != null) {
|
||||
throw new IllegalStateException("Already initialized.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Static to class instance of the class.
|
||||
*/
|
||||
private static final IvoryTower INSTANCE = new IvoryTower();
|
||||
|
||||
/**
|
||||
* To be called by user to obtain instance of the class.
|
||||
*
|
||||
* @return instance of the singleton.
|
||||
*/
|
||||
public static IvoryTower getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
|
||||
*
|
||||
* The MIT License
|
||||
* Copyright © 2014-2022 Ilkka Seppälä
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/** Singleton class. Eagerly initialized static instance guarantees thread safety. */
|
||||
public final class IvoryTower {
|
||||
|
||||
/** Private constructor so nobody can instantiate the class. */
|
||||
private IvoryTower() {
|
||||
// to prevent instantiating by Reflection call
|
||||
if (INSTANCE != null) {
|
||||
throw new IllegalStateException("Already initialized.");
|
||||
}
|
||||
}
|
||||
|
||||
/** Static to class instance of the class. */
|
||||
private static final IvoryTower INSTANCE = new IvoryTower();
|
||||
|
||||
/**
|
||||
* To be called by user to obtain instance of the class.
|
||||
*
|
||||
* @return instance of the singleton.
|
||||
*/
|
||||
public static IvoryTower getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,22 +25,20 @@
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* <p>Double check locking.</p>
|
||||
* Double check locking.
|
||||
*
|
||||
* <p>http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html</p>
|
||||
*
|
||||
* <p>Broken under Java 1.4.</p>
|
||||
* <p>http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
|
||||
*
|
||||
* <p>Broken under Java 1.4.
|
||||
*/
|
||||
public final class ThreadSafeDoubleCheckLocking {
|
||||
/**
|
||||
* Singleton instance of the class, declared as volatile to ensure atomic access by multiple threads.
|
||||
* Singleton instance of the class, declared as volatile to ensure atomic access by multiple
|
||||
* threads.
|
||||
*/
|
||||
private static volatile ThreadSafeDoubleCheckLocking instance;
|
||||
|
||||
/**
|
||||
* private constructor to prevent client from instantiating.
|
||||
*/
|
||||
/** private constructor to prevent client from instantiating. */
|
||||
private ThreadSafeDoubleCheckLocking() {
|
||||
// to prevent instantiating by Reflection call
|
||||
if (instance != null) {
|
||||
|
||||
@@ -25,20 +25,18 @@
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* <p>Thread-safe Singleton class. The instance is lazily initialized and thus needs synchronization
|
||||
* mechanism.</p>
|
||||
*
|
||||
* Thread-safe Singleton class. The instance is lazily initialized and thus needs synchronization
|
||||
* mechanism.
|
||||
*/
|
||||
public final class ThreadSafeLazyLoadedIvoryTower {
|
||||
|
||||
/**
|
||||
* Singleton instance of the class, declared as volatile to ensure atomic access by multiple threads.
|
||||
* Singleton instance of the class, declared as volatile to ensure atomic access by multiple
|
||||
* threads.
|
||||
*/
|
||||
private static volatile ThreadSafeLazyLoadedIvoryTower instance;
|
||||
|
||||
/**
|
||||
* Private constructor to prevent instantiation from outside the class.
|
||||
*/
|
||||
/** Private constructor to prevent instantiation from outside the class. */
|
||||
private ThreadSafeLazyLoadedIvoryTower() {
|
||||
// Protect against instantiation via reflection
|
||||
if (instance != null) {
|
||||
|
||||
@@ -24,17 +24,15 @@
|
||||
*/
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
/**
|
||||
* Application test.
|
||||
*/
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Application test. */
|
||||
class AppTest {
|
||||
|
||||
@Test
|
||||
void shouldExecuteWithoutException() {
|
||||
assertDoesNotThrow(() -> App.main(new String[]{}));
|
||||
assertDoesNotThrow(() -> App.main(new String[] {}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,16 +24,10 @@
|
||||
*/
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* BillPughImplementationTest
|
||||
*
|
||||
*/
|
||||
public class BillPughImplementationTest
|
||||
extends SingletonTest<BillPughImplementation>{
|
||||
/**
|
||||
* Create a new singleton test instance using the given 'getInstance' method.
|
||||
*/
|
||||
public BillPughImplementationTest() {
|
||||
super(BillPughImplementation::getInstance);
|
||||
}
|
||||
/** BillPughImplementationTest */
|
||||
public class BillPughImplementationTest extends SingletonTest<BillPughImplementation> {
|
||||
/** Create a new singleton test instance using the given 'getInstance' method. */
|
||||
public BillPughImplementationTest() {
|
||||
super(BillPughImplementation::getInstance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,31 +24,24 @@
|
||||
*/
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* EnumIvoryTowerTest
|
||||
*
|
||||
*/
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** EnumIvoryTowerTest */
|
||||
class EnumIvoryTowerTest extends SingletonTest<EnumIvoryTower> {
|
||||
|
||||
/**
|
||||
* Create a new singleton test instance using the given 'getInstance' method.
|
||||
*/
|
||||
/** Create a new singleton test instance using the given 'getInstance' method. */
|
||||
public EnumIvoryTowerTest() {
|
||||
super(() -> EnumIvoryTower.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating new instance by reflection.
|
||||
*/
|
||||
/** Test creating new instance by reflection. */
|
||||
@Override
|
||||
@Test
|
||||
void testCreatingNewInstanceByReflection() throws Exception {
|
||||
// Java does not allow Enum instantiation http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9
|
||||
// Java does not allow Enum instantiation
|
||||
// http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9
|
||||
assertThrows(ReflectiveOperationException.class, EnumIvoryTower.class::getDeclaredConstructor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-11
@@ -24,18 +24,11 @@
|
||||
*/
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* InitializingOnDemandHolderIdiomTest
|
||||
*
|
||||
*/
|
||||
class InitializingOnDemandHolderIdiomTest
|
||||
extends SingletonTest<InitializingOnDemandHolderIdiom> {
|
||||
/** InitializingOnDemandHolderIdiomTest */
|
||||
class InitializingOnDemandHolderIdiomTest extends SingletonTest<InitializingOnDemandHolderIdiom> {
|
||||
|
||||
/**
|
||||
* Create a new singleton test instance using the given 'getInstance' method.
|
||||
*/
|
||||
/** Create a new singleton test instance using the given 'getInstance' method. */
|
||||
public InitializingOnDemandHolderIdiomTest() {
|
||||
super(InitializingOnDemandHolderIdiom::getInstance);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,11 @@
|
||||
*/
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* IvoryTowerTest
|
||||
*
|
||||
*/
|
||||
/** IvoryTowerTest */
|
||||
class IvoryTowerTest extends SingletonTest<IvoryTower> {
|
||||
|
||||
/**
|
||||
* Create a new singleton test instance using the given 'getInstance' method.
|
||||
*/
|
||||
/** Create a new singleton test instance using the given 'getInstance' method. */
|
||||
public IvoryTowerTest() {
|
||||
super(IvoryTower::getInstance);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,19 +40,17 @@ import java.util.stream.IntStream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* <p>This class provides several test case that test singleton construction.</p>
|
||||
* This class provides several test case that test singleton construction.
|
||||
*
|
||||
* <p>The first proves that multiple calls to the singleton getInstance object are the same when
|
||||
* called in the SAME thread. The second proves that multiple calls to the singleton getInstance
|
||||
* object are the same when called in the DIFFERENT thread.</p>
|
||||
* object are the same when called in the DIFFERENT thread.
|
||||
*
|
||||
* @param <S> Supplier method generating singletons
|
||||
*/
|
||||
abstract class SingletonTest<S> {
|
||||
|
||||
/**
|
||||
* The singleton's getInstance method.
|
||||
*/
|
||||
/** The singleton's getInstance method. */
|
||||
private final Supplier<S> singletonInstanceMethod;
|
||||
|
||||
/**
|
||||
@@ -64,9 +62,7 @@ abstract class SingletonTest<S> {
|
||||
this.singletonInstanceMethod = singletonInstanceMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the singleton in a non-concurrent setting.
|
||||
*/
|
||||
/** Test the singleton in a non-concurrent setting. */
|
||||
@Test
|
||||
void testMultipleCallsReturnTheSameObjectInSameThread() {
|
||||
// Create several instances in the same calling thread
|
||||
@@ -79,38 +75,36 @@ abstract class SingletonTest<S> {
|
||||
assertSame(instance2, instance3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test singleton instance in a concurrent setting.
|
||||
*/
|
||||
/** Test singleton instance in a concurrent setting. */
|
||||
@Test
|
||||
void testMultipleCallsReturnTheSameObjectInDifferentThreads() {
|
||||
assertTimeout(ofMillis(10000), () -> {
|
||||
// Create 10000 tasks and inside each callable instantiate the singleton class
|
||||
final var tasks = IntStream.range(0, 10000)
|
||||
.<Callable<S>>mapToObj(i -> this.singletonInstanceMethod::get)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
assertTimeout(
|
||||
ofMillis(10000),
|
||||
() -> {
|
||||
// Create 10000 tasks and inside each callable instantiate the singleton class
|
||||
final var tasks =
|
||||
IntStream.range(0, 10000)
|
||||
.<Callable<S>>mapToObj(i -> this.singletonInstanceMethod::get)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
// Use up to 8 concurrent threads to handle the tasks
|
||||
final var executorService = Executors.newFixedThreadPool(8);
|
||||
final var results = executorService.invokeAll(tasks);
|
||||
// Use up to 8 concurrent threads to handle the tasks
|
||||
final var executorService = Executors.newFixedThreadPool(8);
|
||||
final var results = executorService.invokeAll(tasks);
|
||||
|
||||
// wait for all the threads to complete
|
||||
final var expectedInstance = this.singletonInstanceMethod.get();
|
||||
for (var res : results) {
|
||||
final var instance = res.get();
|
||||
assertNotNull(instance);
|
||||
assertSame(expectedInstance, instance);
|
||||
}
|
||||
|
||||
// tidy up the executor
|
||||
executorService.shutdown();
|
||||
});
|
||||
// wait for all the threads to complete
|
||||
final var expectedInstance = this.singletonInstanceMethod.get();
|
||||
for (var res : results) {
|
||||
final var instance = res.get();
|
||||
assertNotNull(instance);
|
||||
assertSame(expectedInstance, instance);
|
||||
}
|
||||
|
||||
// tidy up the executor
|
||||
executorService.shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test creating new instance by reflection.
|
||||
*/
|
||||
/** Test creating new instance by reflection. */
|
||||
@Test
|
||||
void testCreatingNewInstanceByReflection() throws Exception {
|
||||
var firstTimeInstantiated = this.singletonInstanceMethod.get();
|
||||
|
||||
+2
-8
@@ -24,17 +24,11 @@
|
||||
*/
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* ThreadSafeDoubleCheckLockingTest
|
||||
*
|
||||
*/
|
||||
/** ThreadSafeDoubleCheckLockingTest */
|
||||
class ThreadSafeDoubleCheckLockingTest extends SingletonTest<ThreadSafeDoubleCheckLocking> {
|
||||
|
||||
/**
|
||||
* Create a new singleton test instance using the given 'getInstance' method.
|
||||
*/
|
||||
/** Create a new singleton test instance using the given 'getInstance' method. */
|
||||
public ThreadSafeDoubleCheckLockingTest() {
|
||||
super(ThreadSafeDoubleCheckLocking::getInstance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-10
@@ -24,18 +24,11 @@
|
||||
*/
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* ThreadSafeLazyLoadedIvoryTowerTest
|
||||
*
|
||||
*/
|
||||
class ThreadSafeLazyLoadedIvoryTowerTest
|
||||
extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {
|
||||
/** ThreadSafeLazyLoadedIvoryTowerTest */
|
||||
class ThreadSafeLazyLoadedIvoryTowerTest extends SingletonTest<ThreadSafeLazyLoadedIvoryTower> {
|
||||
|
||||
/**
|
||||
* Create a new singleton test instance using the given 'getInstance' method.
|
||||
*/
|
||||
/** Create a new singleton test instance using the given 'getInstance' method. */
|
||||
public ThreadSafeLazyLoadedIvoryTowerTest() {
|
||||
super(ThreadSafeLazyLoadedIvoryTower::getInstance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user