* fix checkstlye errors - visitor pattern * fix checkstlye errors - strategy pattern * fix checkstlye errors - singleton pattern
This commit is contained in:
committed by
Ilkka Seppälä
parent
1eb1961f1b
commit
3b1a28149b
@ -27,40 +27,40 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* <p>Singleton pattern ensures that the class can have only one existing instance per Java
|
||||
* classloader instance and provides global access to it.</p>
|
||||
*
|
||||
* <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 out synchronous and only become async with time, so you it may
|
||||
* not be clear why you are seeing certain changes in behaviour.
|
||||
* <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 giving up control of the instantiation moment, then this implementation 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:
|
||||
* not be clear why you are seeing certain changes in behaviour.</p>
|
||||
*
|
||||
* <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 giving up control of the instantiation moment, then this implementation
|
||||
* will suit you fine.</p>
|
||||
*
|
||||
* <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>
|
||||
* {@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on
|
||||
* -a-singleton-with-javas-enum</p>
|
||||
*
|
||||
* <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>
|
||||
* Another Singleton implementation that is initialized on demand is found in
|
||||
* synchronized.</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
|
||||
* only the method internals on specific conditions.</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.
|
||||
* API level to work.</p>
|
||||
*/
|
||||
public class App {
|
||||
|
||||
|
@ -24,10 +24,10 @@
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* 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>This implementation is thread safe, however adding any other method and its thread safety
|
||||
* is developers responsibility.</p>
|
||||
*/
|
||||
public enum EnumIvoryTower {
|
||||
|
||||
|
@ -24,16 +24,16 @@
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* 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>The Initialize-on-demand-holder idiom is a secure way of creating a lazy initialized singleton
|
||||
* object in Java.</p>
|
||||
*
|
||||
* <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>
|
||||
*
|
||||
* <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>
|
||||
*
|
||||
*/
|
||||
public final class InitializingOnDemandHolderIdiom {
|
||||
@ -44,6 +44,8 @@ public final class InitializingOnDemandHolderIdiom {
|
||||
private InitializingOnDemandHolderIdiom() {}
|
||||
|
||||
/**
|
||||
* Sigleton instance.
|
||||
*
|
||||
* @return Singleton instance
|
||||
*/
|
||||
public static InitializingOnDemandHolderIdiom getInstance() {
|
||||
|
@ -24,11 +24,11 @@
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* Double check locking
|
||||
* <p>
|
||||
* http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
|
||||
* <p>
|
||||
* Broken under Java 1.4.
|
||||
* <p>Double check locking.</p>
|
||||
*
|
||||
* <p>http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html</p>
|
||||
*
|
||||
* <p>Broken under Java 1.4.</p>
|
||||
*
|
||||
* @author mortezaadi@gmail.com
|
||||
*/
|
||||
@ -60,17 +60,21 @@ public final class ThreadSafeDoubleCheckLocking {
|
||||
// Joshua Bloch "Effective Java, Second Edition", p. 283-284
|
||||
|
||||
var result = instance;
|
||||
// Check if singleton instance is initialized. If it is initialized then we can return the instance.
|
||||
// Check if singleton instance is initialized.
|
||||
// If it is initialized then we can return the instance.
|
||||
if (result == null) {
|
||||
// It is not initialized but we cannot be sure because some other thread might have initialized it
|
||||
// in the meanwhile. So to make sure we need to lock on an object to get mutual exclusion.
|
||||
// It is not initialized but we cannot be sure because some other thread might have
|
||||
// initialized it in the meanwhile.
|
||||
// So to make sure we need to lock on an object to get mutual exclusion.
|
||||
synchronized (ThreadSafeDoubleCheckLocking.class) {
|
||||
// Again assign the instance to local variable to check if it was initialized by some other thread
|
||||
// while current thread was blocked to enter the locked zone. If it was initialized then we can
|
||||
// return the previously created instance just like the previous null check.
|
||||
// Again assign the instance to local variable to check if it was initialized by some
|
||||
// other thread while current thread was blocked to enter the locked zone.
|
||||
// If it was initialized then we can return the previously created instance
|
||||
// just like the previous null check.
|
||||
result = instance;
|
||||
if (result == null) {
|
||||
// The instance is still not initialized so we can safely (no other thread can enter this zone)
|
||||
// The instance is still not initialized so we can safely
|
||||
// (no other thread can enter this zone)
|
||||
// create an instance and make it our singleton instance.
|
||||
instance = result = new ThreadSafeDoubleCheckLocking();
|
||||
}
|
||||
|
@ -24,11 +24,11 @@
|
||||
package com.iluwatar.singleton;
|
||||
|
||||
/**
|
||||
* 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.</p>
|
||||
*
|
||||
* Note: if created by reflection then a singleton will not be created but multiple options in the
|
||||
* same classloader
|
||||
* <p>Note: if created by reflection then a singleton will not be created but multiple options
|
||||
* in the same classloader</p>
|
||||
*/
|
||||
public final class ThreadSafeLazyLoadedIvoryTower {
|
||||
|
||||
|
Reference in New Issue
Block a user