Common singleton design pattern (the Singleton)

Singleton pattern (the Singleton)

Singleton object (the Singleton) is a common design pattern. In Java applications, singletons can guarantee a JVM, only one instance of the object exists. This model has several advantages:

  1. Some class creates more frequently, for some large object, which is a lot of overhead.
  2. Eliminating the new operator, reducing the frequency of use of system memory, reduce stress GC.
  3. Some classes, such as the exchange's core trading engine, control the transaction process, if the class can create multiple words, the system is completely chaotic. (For example, there have been more than a military commander to simultaneously command, and will definitely mess), so only use single-case model, in order to ensure that the core transaction server independent control of the entire process.

First, we write a simple singleton class:

public class Singleton {
	/* 持有私有静态实例,防止被引用,此处赋值为 null,目的是实现延迟加载 */
	private static Singleton instance = null;
	
	/* 私有构造方法,防止被实例化 */
	private Singleton() {
	}
	
	/* 静态工程方法,创建实例 */
	public static Singleton getInstance() {
		if (instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

This class meet the basic requirements, but, like there is no thread-safe protection class, if we put it in a multithreaded environment, certainly there will be problems, how to solve? We first think of adding synchronized keyword getInstance method, as follows:

public static synchronized Singleton getInstance() {
	if (instance == null) {
		instance = new Singleton();
	}
	return instance;
}

However, synchronized keyword is locked object, such usage, the performance will decline, because each call to
getInstance (), should be locked object, in fact, only the first created object when you need to lock, then you do not need, so, this place needs to be improved. We changed to the following:

public static Singleton getInstance() {
	if (instance == null) {
		synchronized (instance) {
			if (instance == null) {
				instance = new Singleton();
			}
		}
	}
	return instance;
}

Seems to solve the problems mentioned earlier, the synchronized keyword added to the inside, that is to say when the call is not required when locked, only the instance is null, and create objects only need to lock, performance some improvement. However, such a situation, there still may be a problem, see the following case: create objects and assignment operations are carried out separately in Java instruction, that instance = new Singleton (); statement is executed in two steps. But the JVM does not guarantee the order of these two operations, which means that there may be a new JVM instance Singleton allocate space, then directly assigned instance member, then go to initialize the Singleton instance. This may be wrong, we have to A, B two threads, for example:

  1. A, B threads into the first determining if a
  2. A first enters the synchronized block, since the instance is null, it performs instance = new Singleton ();
  3. Since the optimization mechanism of the internal JVM, JVM first draw some blank memory allocated to the Singleton instance, and assigned to the instance members (note that at this time does not begin to initialize the JVM instance), then left the A synchronized block.
  4. B enters the synchronized block, since this time instance is not null, it immediately left the synchronized block and returns the result to the program that called the method.
  5. At this point B threads plan to use the Singleton instance, only to find that it has not been initialized, so the error occurred. So the program is still possible errors, in fact, during the operation of the program is very complicated, from this point we can see, especially in the writing process more difficult in a multi-threaded environment, challenging. We further optimized the program:
private static class SingletonFactory{
	private static Singleton instance = new Singleton();
}

public static Singleton getInstance(){
	return SingletonFactory.instance;
}

The fact is, singleton inner class implemented to maintain a single embodiment, the JVM internal mechanism to ensure that when a class is loaded, the loading process of this class is the thread mutually exclusive. So that when we first call the getInstance, JVM can help us ensure that instance is created only once, and will ensure that the memory assigned to the instance initialized, so we do not worry about the above issues. Meanwhile, the method will also use mutual exclusion mechanism at the time of the first call, this would resolve the problem of low performance.
So we do a perfect summary of the Singleton pattern:

public class Singleton {

	/* 私有构造方法,防止被实例化 */
	private Singleton() {
	}
	
	/* 此处使用一个内部类来维护单例 */
	private static class SingletonFactory {
		private static Singleton instance = new Singleton();
	}
	
	/* 获取实例 */
	public static Singleton getInstance() {
		return SingletonFactory.instance;
	}
}

In fact it perfect, not necessarily, if an exception is thrown in the constructor, the instance will never be created, will be wrong. So, something is not quite perfect, we can only according to the actual situation, choose the most suitable implementation scenarios. It was this realization: because we only need to be synchronized, so long as the creation and getInstance () to create a separate class at the time, to create a separate add synchronized keyword, it is also possible:

public class SingletonTest {

	private static SingletonTest instance = null;
	
	private SingletonTest() {
	}
	
	private static synchronized void syncInit() {
		if (instance == null) {
			instance = new SingletonTest();
		}
	}
	
	public static SingletonTest getInstance() {
		if (instance == null) {
			syncInit();
		}
		return instance;
	}
}

For performance, the entire program created once instance, so the performance would not be affected.
Through the study of singleton tells us:

  1. Singleton simple to understand, but it still has some specific implementation difficulties.
  2. synchronized keyword lock is the object, when in use, be sure to use (attention to the need to use locking objects and procedures, may sometimes not the whole object and the whole process needs to lock) at the right place.

Here, Singleton has basically been finished, at the end, I suddenly thought of another problem, is to use a static class method to achieve the effect of singletons, also feasible, both here what is the difference?
First, a static class can not implement the interface. (From the class can be said to be, but that destroys the static because the interface has a static method does not allow modification, it is achieved even if the non-static)
Next, single embodiments may be delayed initialize static class generally in the first initialization is first loaded. The reason why the delay in loading, because some classes relatively large, lazy loading so help improve performance.
Again, singleton class can be inherited, his methods can be overridden. But the internal static class methods are static, and can not be overwritten.
Finally, singleton class more flexible, after all, from the realization of just a regular Java class, as long as the basic needs of a single case, you can achieve some other functions inside arbitrary, but not static class.
From the above these generalizations, the basic difference between the two can be seen, but, on the other hand, the final realization of the Singleton pattern above us, inside is to use a static class to implement, so the two are very the association, but we consider the issue of the level difference in terminology. Combination of the two ideas, to create the perfect solution, as HashMap using an array of linked lists + + to achieve the same red-black tree, in fact, are so many things in life, to deal with a single issue in different ways, there are always advantages and disadvantages, the most perfect way is to combine the advantages of each method in order to best solve the problem!

Released seven original articles · won praise 2 · Views 148

Guess you like

Origin blog.csdn.net/lixin_nobody/article/details/104920796