所谓单例模式就是:
a、只能有一个实例(构造私有化)
b、单例类必须自己创建自己的实例
c、单例类必须给他类提供这一个实例(提供实例化的静态方法)
1.1 饿汉式一:
public class Singleton {
private Singleton() {
}
//这里必须静态修饰,否则 getInstance()方法中 return不了singleton
private static Singleton singleton = new Singleton();
public static Singleton getInstance() {
return singleton;
}
}
1.2 饿汉式二:
public class Singleton {
private Singleton() {
}
private static Singleton singleton ;
static {
singleton = new Singleton();
}
public static Singleton getInstance() {
return singleton;
}
}
饿汉式单例在类加载初始化时候就创建好一个静态实例给外部使用,除非系统重启,否则这个实例是不会变的,所以本身是线程安全的
2.1、懒汉式
public class Singleton {
private Singleton() {
}
private static Singleton singleton;
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
懒汉式单例由于延迟加载,所以在多线程环境,可能会出现非单例,不是多线程 环境则无此问题
2.2、验证懒汉式单例在多线程环境下出现的非单例情况
测试类:
public class Test {
public static void main(String[] args) {
//线程一
new Thread(){
@Override
public void run() {
System.out.println(Singleton.getInstance());
}
}.start();
//线程二
new Thread(){
@Override
public void run() {
System.out.println(Singleton.getInstance());
}
}.start();
}
}
在懒汉式单例中,设置休眠
public class Singleton {
private Singleton() {
}
private static Singleton singleton;
public static Singleton getInstance() {
if (singleton == null) {
try {
Thread.sleep(10);//设置休眠
} catch (Exception e) {
e.printStackTrace();
}
singleton = new Singleton();
}
return singleton;
}
}
运行测试类可以看到,多线程环境下出现的非单例情况:
2.3、改进懒汉式单例,使其在多线程环境下也不出现非单例情况
解决方式加同步锁:
public class Singleton {
private Singleton() {
}
private static Singleton singleton;
//加同步锁
synchronized public static Singleton getInstance() {
if (singleton == null) {
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
singleton = new Singleton();
}
return singleton;
}
}
public class Singleton {
private Singleton() {
}
private static Singleton singleton;
public static Singleton getInstance() {
synchronized(Singleton.class){//同步锁加在这里也可
if (singleton == null) {
try {
Thread.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
singleton = new Singleton();
}
}
return singleton;
}
}
3.1、使用内部类实现单例
public class Singleton {
private Singleton(){
}
//静态内部类
//外部类被加载,内部类没有被加载,除非内部类被使用才会被加载
private static class InSideClass{
private static Singleton singleton = new Singleton();
}
public static Singleton getInstance() {
return InSideClass.singleton;
}
}