单例模式(Singleton Pattern)是Java设计模式中常用的模式之一。
单例模式是保证在程序的运行期,一个类的对象只有一个,构造方法只执行一次,得到的所有引用指向都是同一个对象。是一种最佳的创建对象的方式,它涉及到的只是一个单一的类,这个类负责创建自己的对象,同时确保只有单个对象被创建。包括提供一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
所以这也是被很多人人称之为懒汉模式或者饿汉模式的模式的原因。当然了,这两者是有区别的。
在类加载的时候就执行实例化对象的操作。在调用特定的方法(getInstance)的时候,才去实例(调用的是构造方法)对象;
关键代码:构造函数是私有的。
注意:
- 1、单例类只能有一个实例。
- 2、单例类必须自己创建自己的唯一实例。
- 3、单例类必须给所有其他对象提供这一实例。
实现
我们将创建一个 SingleObject 类。SingleObject 类有它的私有构造函数和本身的一个静态实例。
SingleObject 类提供了一个静态方法,供外界获取它的静态实例。SingletonPatternDemo,我们的演示类使用 SingleObject 类来获取 SingleObject对象。
类图如下:
代码如下:
创建一个 Singleton 类。
1 public class SingleObject { 2 3 //创建 SingleObject 的一个对象 4 private static SingleObject instance = new SingleObject(); 5 6 //让构造函数为 private,这样该类就不会被实例化 7 private SingleObject(){} 8 9 //获取唯一可用的对象 10 public static SingleObject getInstance(){ 11 return instance; 12 } 13 14 public void showMessage(){ 15 System.out.println("Hello World!"); 16 } 17 }
从 singleton 类获取唯一的对象。
1 public class SingletonPatternDemo { 2 public static void main(String[] args) { 3 4 //不合法的构造函数 5 //编译时错误:构造函数 SingleObject() 是不可见的 6 //SingleObject object = new SingleObject(); 7 8 //获取唯一可用的对象 9 SingleObject object = SingleObject.getInstance(); 10 11 //显示消息 12 object.showMessage(); 13 } 14 }
单例模式的几种常见形式
- 饿汉式:直接创建对象,不存在线程安全问题
- 直接实例饿汉式(简介直观)
-
/** * 饿汉式 * 直接创建实例 对象,不管你是否徐亚这个对象都会创建 * * 1)构造器私有化 * 2)自行创建,并且静态变量保存 * 3)向外提供这个实例 * 4)强调这是一个实例,我们可以用final修改 * @author dell * */ public class Singleton1 { public final static Singleton1 instance = new Singleton1(); private Singleton1() { } }
-
- 枚举式(最简洁)
-
package com.etc.Singleton; /** * 枚举类型,表示该类型的对象是有限的几个 * 我们可以限定成一个,就成了单例 * @author dell * */ public enum Singleton2 { INSTANCE }
-
- 静态代码饿汉式(适合复杂实例化)
-
public class Singleton3 { public static final Singleton3 INSTANCE; private String info; static { try { //这是我自己写的类加载配置文件 //里面有一个信息info=HuaChenYu Properties pro = new Properties(); pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties")); INSTANCE = new Singleton3(pro.getProperty("info")); } catch (IOException e) { // TODO Auto-generated catch block throw new RuntimeException(); } } private Singleton3(String info){ this.info = info; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Override public String toString() { return "Singleton3 [info=" + info + "]"; } }
-
- 懒汉式:延迟创建对象
- 线程不安全(适用于单线程)
- Singleton类
/** * 懒汉式: * 延迟创建实力对象 * * 1)构造器私有化 * 2)静态变量保存唯一实例 * @author dell * */ public class Singleton4 { private static Singleton4 INSTANCE; private Singleton4() { } public static Singleton4 getInstance() { if(INSTANCE == null) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } INSTANCE = new Singleton4(); } return INSTANCE; } }
- Test测试类
public class Test { public static void main(String[] args) throws Exception, ExecutionException { // TODO Auto-generated method stub Callable<Singleton4> c = new Callable<Singleton4>() { @Override public Singleton4 call() throws Exception { // TODO Auto-generated method stub return Singleton4.getInstance(); } }; ExecutorService es = Executors.newFixedThreadPool(2); Future<Singleton4> f1 = es.submit(c); Future<Singleton4> f2 = es.submit(c); Singleton4 s1 = f1.get(); Singleton4 s2 = f2.get(); System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); es.shutdown(); } }
- Singleton类
- 线程安全(适用于多线程)
- Singleton类
public class Singleton5 { private static Singleton5 INSTANCE; private Singleton5() { } public static Singleton5 getInstance() { //为了提高性能添加一个判断条件 //在第一次实现的时候会因为多个线程同时抢的情况 //那在后面以及实例过后就不会再次执行了 if(INSTANCE == null) { synchronized (Singleton5.class) { if(INSTANCE == null) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } INSTANCE = new Singleton5(); } } } return INSTANCE; } }
- Test测试类
package com.etc.Singleton; import java.lang.reflect.Executable; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Test { public static void main(String[] args) throws Exception, ExecutionException { // TODO Auto-generated method stub Callable<Singleton5> c = new Callable<Singleton5>() { @Override public Singleton5 call() throws Exception { // TODO Auto-generated method stub return Singleton5.getInstance(); } }; ExecutorService es = Executors.newFixedThreadPool(2); Future<Singleton5> f1 = es.submit(c); Future<Singleton5> f2 = es.submit(c); Singleton5 s1 = f1.get(); Singleton5 s2 = f2.get(); System.out.println(s1 == s2); System.out.println(s1); System.out.println(s2); es.shutdown(); } }
- Singleton类
- 静态内部类形式(适用于多线程)
-
/** * 在内部类被加载和初始化的时候,才创建INSTANCE实例对象. * 静态内部诶不会自动化随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的。 * 因为是在内部类加载和初始化时创建的,因此线程是安全的。 */ public class Singleton6 { private Singleton6() { } private static class Inner { private static final Singleton6 INSTANCE = new Singleton6(); } public static Singleton6 getInstance(){ return Inner.INSTANCE; } }
-
- 线程不安全(适用于单线程)