在一个应用程序里面,某个类的实例对象只有一个,你没办法去new,因为构造器是被 private 修饰的,易班通过其get方法获取到他们的实例。

懒汉式单例

  1. // 线程不安全
  2. public class Singleton {
  3. private static Singleton singleton;
  4. private Singleton() {
  5. }
  6. public static Singleton getInstance() {
  7. if(singleton == null) {
  8. singleton = new Singleton();
  9. }
  10. return singleton;
  11. }
  12. }
  13. // 线程安全
  14. public class Singleton {
  15. private static Singleton singleton;
  16. private Singleton() {
  17. }
  18. public static synchronized Singleton getInstance() {
  19. if(singleton == null) {
  20. singleton = new Singleton();
  21. }
  22. return singleton;
  23. }
  24. }

懒汉式单例—双重检验

  1. public class Singleton {
  2. // volatile 避免指令重排序问题
  3. private volatile static Singleton singleton;
  4. private Singleton () {
  5. }
  6. public static Singleton getInstance() {
  7. if(singleton == null) {
  8. synchronized(Singleton.class) {
  9. if(singleton == null) {
  10. // 保证singleon在多线程中的可见性,可以立即刷新到主内存
  11. // new Singleton() (1-开辟空间,2-初始化空间,3-赋值实例对象)
  12. // 操作会发生指令重排
  13. // new创建了实例并赋值给了singleton,但是构造方法初始化空间步骤并未执行
  14. singleton = new Singleton();
  15. }
  16. }
  17. }
  18. return singleton;
  19. }
  20. }

饿汉式单例

  1. // 静态常量方式
  2. public class Singleton {
  3. private final static Singleton instance = new Singleton();
  4. private Singleton() {
  5. }
  6. public static Singleton getInstance() {
  7. return instance;
  8. }
  9. }
  10. // 静态代码块方式
  11. public class Singleton {
  12. private static Singleton instance;
  13. static {
  14. instance = new Singleton();
  15. }
  16. private Singleton() {
  17. }
  18. public static Singleton getInstance() {
  19. return instance;
  20. }
  21. }

静态内部类

  1. public class Singleton {
  2. private static class SingletonHolader {
  3. private static final Singleton INSTANCE = new Singleton();
  4. }
  5. private Singleton() {
  6. }
  7. public static final Singleton getInstance() {
  8. return SingletonHolder.INSTANCE;
  9. }
  10. }

枚举

  1. public enum Singleton {
  2. INSTANCE;
  3. public void whateverMethod() {
  4. }
  5. }

实际应用场景

1、在Spring中创建的Bean实例默认都是单例模式存在的。
2、网站的计数器,一般也是单例模式实现,否则难以同步。
3、应用程序的日志应用,一般都用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。