众所周知,单例是只在程序运行的时候只有一个实例,在单线程的情况之下单例很容易实现,但是在多线程的时候,如何做到单例呢?
第一种方式就是采取静态内部类,看代码展示:
package com.tgb.thread;
/**
* Created by oxj on 2017/8/12.
*/
public class InnerSingleton {
private InnerSingleton(){ }
public static InnerSingleton getInstance()
{
return Nested.instance;
}
//静态内部类方式:在第一次被引用时被加载
static class Nested
{
private static InnerSingleton instance = new InnerSingleton();
}
//测试
public static void main(String args[])
{
//第一个线程
new Thread(new Runnable() {
public void run() {
InnerSingleton.getInstance();
System.out.println(InnerSingleton.getInstance().hashCode());
}
}).start();
//第二个线程
new Thread(new Runnable() {
public void run() {
InnerSingleton.getInstance();
System.out.println(InnerSingleton.getInstance().hashCode());
}
}).start();
}
}
为了查看示例代码中的线程是否是用的同一个实例,我将线程中实例的hashcode打印了出来,看下列结果:
hashcode是一样的,表明在多线程中他们用的是同一个实例。
接下来我们看另外一种方式实现多线程中的单例—双重检测机制(Double Check)。
同样是代码展示:
package com.tgb.thread;
/**
* Created by oxj on 2017/8/12.
*/
public class DoubleCheckSingleton {
private DoubleCheckSingleton (){};
private static DoubleCheckSingleton instance;
public static DoubleCheckSingleton getInstance(){
if (instance==null){
try {
//模拟初始化对象准备时间
Thread.sleep(3000);
}catch (Exception e){
e.printStackTrace();
}
synchronized (DoubleCheckSingleton.class){
if(instance==null){
instance=new DoubleCheckSingleton();
}
}
}
return instance;
}
//测试
public static void main(String args[])
{
//第一个线程
new Thread(new Runnable() {
public void run() {
DoubleCheckSingleton.getInstance();
System.out.println(DoubleCheckSingleton.getInstance().hashCode());
}
}).start();
//第二个线程
new Thread(new Runnable() {
public void run() {
DoubleCheckSingleton.getInstance();
System.out.println(DoubleCheckSingleton.getInstance().hashCode());
}
}).start();
}
}
查看结果:
无论是静态内部类还是双重检测机制都可以实现多线程下的单例,而且都很方便,大家任选一种即可。