单例模式
模式是脱离语言的。
问题的由来:
为什么?
多个线程操作不同实例对象。多个线程要操作同一对象,要保证对象的唯一性
解决的问题:
实例化过程中只实例化一次
解决的思路
有一个实例化的过程(只有一次),产生实例化对象 new
提供返回实例对象的方法 getInstace()
单例模式的分类
1.饿汉式
线程安全:在类加载时候已经被实例化一次,所以只有这一次,线程安全
懒加载:没有延迟加载,如果好长时间不使用,影响性能
public class HungerySingletonDemo {
//加载时产生实例对象
private static HungerySingletonDemo getInstance = new HungerySingletonDemo();
private HungerySingletonDemo(){
}
public static HungerySingletonDemo getInstance(){
return getInstance;
}
//测试代码
public static void main(String[] args) {
HungerySingletonDemo singletonDemo = HungerySingletonDemo.getInstance();
//多线程
for (int i = 0; i < 20 ; i++) {
new Thread(()->{
System.out.println(HungerySingletonDemo.getInstance());
}).start();
}
}
}
2.懒汉式
线程不安全,不能保证实例对象的唯一性,实现了懒加载,性能好,两个线程同时判断 null=instance 执行new对象就不能保证只有一个实例对象了
public class HoonSingleton {
private static HoonSingleton instance;
private HoonSingleton(){}
public static HoonSingleton getInstance(){
if(null == instance){
instance = new HoonSingleton();
}
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 20 ; i++) {
new Thread(()->{
System.out.println( HoonSingleton.getInstance());
}).start();
}
}
}
3.懒汉式+同步方法
线程安全,实现懒加载,synchronized退化到了串行执行
public class HoonSyncSingleton {
private static HoonSyncSingleton instance;
private HoonSyncSingleton(){}
public synchronized static HoonSyncSingleton getInstance(){
if(null == instance)
instance = new HoonSyncSingleton();
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 20 ; i++) {
new Thread(()->{
System.out.println(HoonSyncSingleton.getInstance());
}).start();
}
}
}
4.DCL
线程安全,实现懒加载 ,问题:因为指令重拍引起空指针异常
public class DCLSingleton {
private static DCLSingleton instance;
private DCLSingleton(){
}
public static DCLSingleton getInstance(){
if( null == instance){
synchronized (DCLSingleton.class){
if(null == instance){
instance = new DCLSingleton();
}
}
}
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(()->{
System.out.println(DCLSingleton.getInstance());
}).start();
}
}
}
5.Volatile+Double-check
只是在上一代码中增加了一个volatie关键字,进行了优化
public class DCLVolatileSingleton {
private volatile static DCLVolatileSingleton instance;
private DCLVolatileSingleton(){
}
public static DCLVolatileSingleton getInstance(){
if( null == instance){
synchronized (DCLVolatileSingleton.class){
if(null == instance){
instance = new DCLVolatileSingleton();
}
}
}
return instance;
}
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(()->{
System.out.println(DCLVolatileSingleton.getInstance());
}).start();
}
}
}
6.内部类(推荐使用)
实现了懒加载, 没有使用锁, 内部类不会加载,只有主动调用才会加载
声明类的时候,成员变量中不声明实例变量,而放到内部静态类中,
public class HolderSingleton {
private HolderSingleton(){
}
private static class Holder{
private static HolderSingleton instance = new HolderSingleton();
}
public static HolderSingleton getInstance(){
return Holder.instance;
}
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(()->{
System.out.println(HolderSingleton.getInstance());
}).start();
}
}
}
7.枚举(推荐使用)
public class EnumSingletom {
private EnumSingletom() {}
public static EnumSingletom getInstance() {
return EnumHolder.INSTANCE.instance;
}
//内部类延迟加载
private enum EnumHolder {
INSTANCE;
private EnumSingletom instance;
EnumHolder() {
this.instance = new EnumSingletom();
}
private EnumSingletom getInstance() {
return instance;
}
}
}