單例模式應該大家都學習過。單一個對象需要被頻繁使用,使用單例模式,可以節省建立對象消耗的時間,也能節省記憶體。下面介紹幾種單例的建立方法,和性能對比。
(1)普通方式,私有化構造函數,使用靜态變量進行初始化,在類被加載的時候初始化
class Singleton
{
private static Singleton instance = new Singleton();
private Singleton()
{
System.out.println("Singleton is create");
}
public static Singleton getInstance()
{
return instance;
}
public static void createString()
{
System.out.println("createString in Singleton");
}
}
(2)延遲加載的單例模式(懶漢模式),當第一次調用的時候,初始化執行個體,需使用同步機制,保證線程安全
class LazySingleton
{
private LazySingleton()
{
System.out.println("LazySingleton is create");
}
private static LazySingleton instance = null;
public static synchronized LazySingleton getInstance()
{
if(instance == null)
{
instance = new LazySingleton();
}
return instance;
}
}
(3)使用内部靜态内部類的單例模式,使用内部類,讓jvm虛拟機,直接保證線程安全,該方法優于(2)
class StaticSingleton
{
private StaticSingleton()
{
System.out.println("StaticSingleton is create");
}
private static class SingletonHolder
{
private static StaticSingleton instance = new StaticSingleton();
}
public static StaticSingleton getInstance()
{
return SingletonHolder.instance;
}
public static void createString()
{
System.out.println("createString in Singleton");
}
}
(4)對比(1)(2)(3)三種模式的單例模式性能
import java.io.*;
public class SingletonTest {
public static void main(String[] args) {
StaticSingleton.createString();
long time = System.currentTimeMillis();
System.out.println("time is "+time);
int max = 1000000;
for(int i = 0; i < max;i++)
{
Singleton.getInstance();
}
System.out.println("spend :"+(System.currentTimeMillis() - time));
time = System.currentTimeMillis();
for(int i = 0; i < max;i++)
{
LazySingleton.getInstance();
}
System.out.println("spend :"+(System.currentTimeMillis() - time));
time = System.currentTimeMillis();
for(int i = 0; i < max;i++)
{
StaticSingleton.getInstance();
}
System.out.println("spend :"+(System.currentTimeMillis() - time));
}
結果如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2Lc1TVE9ENnJzYoVjMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DO1cDM1gDN5EDOxYDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
有此可見,性能(1)(3),優于(2),當我們需要延長加載時(加快啟動速度),可以使用(3)來替代(2)。
(5)進階,在有對象被序列化,如何保證單例模式的對象唯一? 答案就是重寫readResolve()方法。具體代碼如下
class SerSingleton implements Serializable
{
String name;
private SerSingleton()
{
System.out.println("Singleton is create");
name = "SerSingleton";
}
private static SerSingleton instance = new SerSingleton();
public static SerSingleton getInstance()
{
return instance;
}
public static void createString()
{
System.out.println("createString in Singleton");
}
private Object readResolve()
{
//阻止新生成的新執行個體,總是傳回目前對象
return instance;
}
}