java 单例模式

单例模式有以下特点:
1.单例类只能有一个实例(该类只能有一个实例)
2.单例类必须自己创建实例
3.单例类必须给所有其他对象提供这一实例
计算机系统中,如线程池、缓存、日志对象、驱动程序等被设置成单例。在多线程环境下,可能有一些同步问题。
如下代码所示:

public class TestStream {
     private String name;
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this.name = name;
     } 
     //该类只能有一个实例
     private TestStream(){}    //私有无参构造方法
     //该类必须自行创建
     //有2种方式
     /*private static final TestStream ts=new TestStream();*/
     private static TestStream ts1=null;//懒汉单例模式
     //这个类必须自动向整个系统提供这个实例对象
     public static TestStream getTest(){//这里用的是懒汉单例模式
         if(ts1==null){
             ts1=new TestStream();
         }
         return ts1;
     }
     public void getInfo(){
         System.out.println("output message "+name);
     }
 }
public class TestMain {
     public static void main(String [] args){
         TestStream s=TestStream.getTest();
         s.setName("张孝祥");
         System.out.println(s.getName());
         TestStream s1=TestStream.getTest();
         s1.setName("张孝祥");
         System.out.println(s1.getName());
         s.getInfo();
         s1.getInfo();
         if(s==s1){
             System.out.println("创建的是同一个实例");
         }else if(s!=s1){
             System.out.println("创建的不是同一个实例");
         }else{
             System.out.println("application error");
         }
     }
 }

运行结果: 
张孝祥  
张孝祥  
output message 张孝祥  
output message 张孝祥  
创建的是同一个实例
懒汉单例模式:默认不自动实例化,等用的时候根据当前情况实例化

public class Singleton{
  private static Singleton instance = null;
  private Singleton(){}
  public static Singleton getInstance(){
    if(instance == null)  
        return new Singleton();
     else
        return instance;
}
}

饿汉单例模式:在类第一次加载的时候强制实例化

public class Singleton{
  private static Singleton instance = new Singleton();
  private Singleton(){}
  public static Singleton getInstance(){
        return instance;
}
}

单例模式的线程同步问题:
两个线程,一个发现变量是null,准备创建变量,第二个也发现变量是null,创建变量,就会造成在一个JVM中有多个单例类型的实例。
解决线程安全的方案:
1.使用synchronized方法对getInstance()方法进行同步

public class Singleton{
  private static Singleton instance = null;
  private Singleton(){}
  public synchronized  static Singleton getInstance(){
    if(instance == null)  //mark1
        return new Singleton();//mark2
     else
        return instance;
}
}

2.双重锁
但是用synchoronized会导致性能下降,我们想要的只是mark1和mark2的同步,所以可以不把synchronized加在方法上,而是加在代码块里

public class Singleton{
  private static volatile Singleton instance;
  
  private static Singleton(){}
  
  public static Singleton getSingleton(){
      if(instance == null){//mark1
        synchronized(Singleton.class){
            if(instance == null)//mark2
  return new Singleton();
             return instance;
}
return instance;
}    

}
}

这里用了两个判断,原因:如果两个线程同时到达mark1处,synchronized可以保证线程不同时进行,但两个线程会一个个执行,所以还要在synchronized代码块中再次判断,防止创建两个。
这个也叫作双重锁。
3.使用静态内部类
这种方法拥有单例、延迟创建(参见饿汉模式)和线程同步的优点,利用静态内部类来实现

public class Singleton{
    private static Singleton(){}
    
    private static class Lazyholder{
     private static final Singleton instance = new Singleton();
}

  public static Singleton getSingleton(){
  return Lazyholder.instance;
}
}

当类被加载时,由于没有static代码,所以不会有操作。当第一次执行getSingleton()方法时,内部静态类会被加载,创建外部单例类实例,在内部类加载过程中,静态类只会被加载一次,static属性和static初始化块的执行是串行的,这就保证了不会有两个线程同时new Singleton()

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、前言 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为...
    manimaniho阅读 478评论 0 0
  • 学习资料: Java 的 23 种设计模式全解析 《Java程序性能优化》 《Java程序性能优化》,这本书蛮不错...
    英勇青铜5阅读 652评论 5 4
  • 目录一.什么是单例?二.有几种?三.应用场景四.注意的地方 一.什么是单例? 单例模式 保证一个类在内存中只有一个...
    在挖坑的猿阅读 916评论 0 0
  • 单例模式简介 在GoF的23种设计模式中,单例模式是比较简单的一种。然而,有时候越是简单的东西越容易出现问题。下面...
    王帅199207阅读 1,540评论 0 107
  • 今天分享来自《浮生六记》这本书的十点感悟: 001 在“女子无才便是德”的时代,才女自然是十分稀缺的,陈芸根据背诵...
    饼姑娘阅读 316评论 0 0

友情链接更多精彩内容