概述
对某个类只存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)
饿汉式(静态变量)
public class Singleton1 {
public static void main(String[] args) {
//测试
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance==instance1); //true
System.out.println(instance.hashCode()==instance1.hashCode()); //true
}
}
/**
* 饿汉式 (静态变量)
*/
class Singleton {
//构造器私有化,外部不能new
private Singleton() {
}
//本类内部创建对象实例
private final static Singleton instance = new Singleton();
//提供一个共有的静态方法、返回实例对象
public static Singleton getInstance() {
return instance;
}
}
优点:
避免了线程同步问题
缺点:
在类装载的时候就完成了实例化,没有达到Lazy loading效果、并且容易造成内存浪费
饿汉式(静态代码块)
public class Singleton2 {
public static void main(String[] args) {
//测试
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance == instance1); //true
System.out.println(instance.hashCode() == instance1.hashCode()); //true
}
}
/**
* 饿汉式 (静态代码块)
*/
class Singleton {
//构造器私有化,外部不能new
private Singleton() {
}
//本类内部创建对象实例
private static Singleton instance;
static { //在静态代码块中创建单例对象
instance = new Singleton();
}
//提供一个共有的静态方法、返回实例对象
public static Singleton getInstance() {
return instance;
}
}
优缺点与饿汉式(静态变量)类似!
懒汉式(线程不安全)
public class Singleton3 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance == instance1); //true
System.out.println(instance.hashCode() == instance1.hashCode()); //true
}
}
class Singleton {
private static Singleton instance;
private Singleton() {
}
//提供一个静态公有方法、使用到该方法才去创建
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
优点:
调用getInstance()
方法时,才创建instance
实例
缺点:
若多线程情况下同时进入getInstance()
的if
方法中,会创建多个Singleton()
实例.线程不安全!
懒汉式(线程安全,同步方法)
public class Singleton4 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance == instance1); //true
System.out.println(instance.hashCode() == instance1.hashCode()); //true
}
}
class Singleton {
private static Singleton instance;
private Singleton() {
}
//提供一个静态公有方法、使用到该方法才去创建
//加入synchronized关键字,使得线程安全
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
优点:
解决了线程不安全的问题
缺点:
效率低!每次调用getInstance()
都要进行同步
懒汉式(线程安全,同步代码块)
public class Singleton5 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance == instance1); //true
System.out.println(instance.hashCode() == instance1.hashCode()); //true
}
}
class Singleton {
private static Singleton instance;
private Singleton() {
}
//提供一个静态公有方法、使用到该方法才去创建
//加入synchronized关键字,使得线程安全
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
instance = new Singleton();
}
}
return instance;
}
直接导致线程不安全!
双重检查
public class Singleton6 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance == instance1); //true
System.out.println(instance.hashCode() == instance1.hashCode()); //true
}
}
class Singleton {
private static volatile Singleton instance;
private Singleton() {
}
//提供一个静态公有方法、加入双重检查代码、解决线程安全与懒加载问题!
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
优点:
解决了线程安全、懒加载、效率的问题!
举例:
若A、B线程进入了if
中,A创建了Singleton()
实例,B再进入synchronized
代码块中时,instance
已经被创建,直接返回. 之后进入的线程则直接返回instance
静态内部类
public class Singleton7 {
public static void main(String[] args) {
Singleton instance = Singleton.getInstance();
Singleton instance1 = Singleton.getInstance();
System.out.println(instance == instance1); //true
System.out.println(instance.hashCode() == instance1.hashCode()); //true
}
}
//静态内部类
class Singleton {
private Singleton() {
}
//写一个静态内部类,该类中由一个静态属性singleton
private static class singletonInstance {
private final static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return singletonInstance.instance;
}
}
优点:
1、调用getInstance()
才去装载singletonInstance
类去创建 Singleton()
完成实例化.
2、JVM底层装载类的时候是线程安全的饿
2、线程安全、延迟加载、效率高
枚举
public class Singleton8 {
public static void main(String[] args) {
Singleton instance1 = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance1==instance2);
System.out.println(instance1.hashCode()==instance2.hashCode());
instance1.sayOk();
instance2.sayOk();
}
}
//静态内部类
enum Singleton {
INSTANCE;
public void sayOk() {
System.out.println("ok");
}
}
优点:
避免多线程同步问题、防止反序列化重新创建对象
JDK中的单例模式
Runtime采用了饿汉式:简单,类装载就创建实例