最近在看《剑指offer》这本书,虽说之前也看过,但是看得比较粗糙,决定重新看过。这本书也是公认的面试宝典,对程序猿找工作大有裨益,本书算法实现大部分是C/C++,也有部分C#代码。本人学习Java的,也能读懂C/C++和C#代码,但是我希望用Java实现一下本书算法,一来可以锻炼一下自己,二来通过比较不同语言实现同一算法的不同之处,体会一下其中奥妙。好吧,下面我们就来学习一下使用Java语言实现的Singleton模式。
一、 只适用于单线程环境
public class Singleton1
{
private static Singleton1 instance = null;
private Singleton1()
{
}
public static Singleton1 Instance()
{
if(null == instance)
{
instance = new Singleton1();
System.out.println("创建实例");
}
return instance;
}
public static void main(String[] args) {
Singleton1.Instance(); //打印:创建实例
Singleton1.Instance(); //不打印
Singleton1.Instance(); //不打印
}
}
优点:适合单线程环境,当instance为null时才创建实例,避免重复创建。其中,将构造函数定义为私有函数是关键。
缺点:当然是不适合多线程环境咯。
二、 虽然在多线程环境中能工作但效率不高
public class TestThread extends Thread{
@Override
public void run()
{
try
{
Singleton2.Instance();
sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public class Singleton2 {
private static Singleton2 instance = null;
private static Object object = new Object();
private Singleton2()
{
}
public static Singleton2 Instance()
{
synchronized(object)
{
if(null == instance)
{
instance = new Singleton2();
System.out.println("创建实例");
}else
{
System.out.println("实例已存在");
}
}
return instance;
}
public static void main(String[] args) {
//循环创建线程,并调用Instance函数,最终"创建实例"只打印1次,代码正确。
while(true)
{
new TestThread().start();
}
}
}
缺点:当通过Instance函数得到Singleton2实例时,都会试图加上一个同步锁,但是加锁非常耗时,因此这里有待进一步改进。
三、 加同步锁前后两次判断实例是否已存在
public class Singleton3 {
private static Singleton3 instance = null;
private static Object object = new Object();
private Singleton3() {
}
public static Singleton3 Instance() {
if (null == instance)
{
synchronized (object)
{
if (null == instance)
{
instance = new Singleton3();
}
}
}
return instance;
}
}
缺点:代码复杂,易出错。
四、 利用静态构造函数(也叫饿汉式)
public class Singleton4 {
private static Singleton4 instance = new Singleton4();
private Singleton4()
{
}
public static Singleton4 Instance()
{
return instance;
}
}
缺点:没有实现按需创建实例,降低了内存使用效率。
PS:与饿汉式相对的为懒汉式,即对象是方法被调用时才初始化,也叫做对象的延时加载。
五、 实现按需创建实例
public class Singleton5 {
private Singleton5()
{
}
public static Singleton5 Instance()
{
return SingletonHelper.instance;
}
private static class SingletonHelper
{
private final static Singleton5 instance = new Singleton5();
}
}
此方法使用了静态内部类,是目前为止比较优秀的解法之一,真正做到了按需创建。
写博文经验尚浅,如有错误之处,还望各位大神指出,谢谢。