• 张小二求职记之 单例模式(三)之决战多线程


    M:上回说的多线程的单例模式会了?

    z;略懂

    M:写一个吧

    package 单例模式;
    
    
    public class Singleton {
        private static Singleton instance=null;
    
        
        private Singleton()
        {
            System.out.println("单例构造函数");
        }
        
        public  static  Singleton getInstance()
        {
            if(instance==null)
            {
                instance=new Singleton();
            }
            return instance;
            
        }
        
        
    
    
        public static void main(String[] args) {
            
            //创建50个线程,对非同步的方法getinstance 就行获取对象
            for(int i=0;i<30;i++)
            {
            new Thread(new Runnable(){
    
                @Override
                public void run() {
                   
                  System.out.println(Singleton.getInstance());
                }
                
                
            }).start();
            }
            
            
        
        }
    
    }
    部分结果如下,发现出现了不同的实例
    例构造函数
    单例构造函数
    单例模式.Singleton@75da931b
    单例构造函数
    单例构造函数
    单例模式.Singleton@34780af5
    单例模式.Singleton@34780af5
    单例构造函数
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@34780af5
    单例模式.Singleton@2b1be57f
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@2b1be57f
    单例模式.Singleton@60f00e0f
    单例模式.Singleton@157ee3e5
    

    加入synchronized部分结果如下:全部都唯一啊,你自己试试。

    例构造函数
    单例模式.Singleton@78214f6b
    单例模式.Singleton@78214f6b
    单例模式.Singleton@78214f6b
    单例模式.Singleton@78214f6b
    单例模式.Singleton@78214f6b
    单例模式.Singleton@78214f6b

    M:用了synchronized方法是吧,修饰静态方法,相当于对什么加锁

    ,相当于对sinleton.class加锁

    M:不错,多线程可以提高程序的并发程度,从而提高程序执行效率,但是多线程本身,尤其是同步,会引起锁的竞争,我就问你了,如何减少锁的竞争,改造本方法,并举个其他的例子?

    z:减少的所得粒度和上锁的范围。比如数据库中有对表 页 行 加锁,粒度低了,锁的竞争就减少了。

    比如在读写锁,如果只有一种锁的,那么SS也是互斥的,通过将锁分割成读写锁,减少了竞争。

    对于队列解锁,我可以设置头设置一个锁,尾巴设置一个锁,这样不就减小了锁的粒度,

    还有并行的hashmap、

    M:呵呵,知道不少,写代码吧,分析这个问题:

    z: 本文中synchronzide同步的粒度大,因为instance=!=null不用加锁。

    所以改造如下;

    package 单例模式;
    
    
    public class Singleton {
        private static Singleton instance=null;
    
        
        private Singleton()
        {
            System.out.println("单例构造函数");
        }
        
        public  static  Singleton getInstance()
        {
            if(instance==null)
            {
            synchronized(Singleton.class)
            {
            if(instance==null)
            {
                instance=new Singleton();
            }
            }
            }
            return instance;
            
        }
        
        
    
    
        public static void main(String[] args) {
            
            //创建50个线程,对非同步的方法getinstance 就行获取对象
            for(int i=0;i<30;i++)
            {
            new Thread(new Runnable(){
    
                @Override
                public void run() {
                   
                  System.out.println(Singleton.getInstance());
                }
                
                
            }).start();
            }
            
            
            
            
                   
    
        
        }
    
    }

    M:双重锁检查,为什么要双重锁?

    第一步:只有为空才会进同步块,说了,如果有了实例就直接返回结果

    第二部:判断为空:按照线程的不可确定性,两个线程同时判断

    if(instance==null) 都会先后进入同步快,为出现创建两个实例

    package 单例模式;
    
    
    public class Singleton {
        private static Singleton instance=null;
    
        
        private Singleton()
        {
            System.out.println("单例构造函数");
        }
        
        public  static  Singleton getInstance()
        {
            if(instance==null)
            {
            synchronized(Singleton.class)
            {
        
            
                instance=new Singleton();
            
            }
            }
            return instance;
            
        }
        
        
    
    
        public static void main(String[] args) {
            
            //创建50个线程,对非同步的方法getinstance 就行获取对象
            for(int i=0;i<100;i++)
            {
            new Thread(new Runnable(){
    
                @Override
                public void run() {
                   
                  System.out.println(Singleton.getInstance());
                }
                
                
            }).start();
            }
            
            
            
            
            
        
            
    
        
        }
    
    }
    结果出现重复

    例构造函数
    单例构造函数
    单例模式.Singleton@46993aaa
    单例模式.Singleton@52e5376a
    单例模式.Singleton@46993aaa
    单例模式.Singleton@46993aaa
    单例模式.Singleton@46993aaa
    单例模式.Singleton@46993aaa
    单例构造函数
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@46993aaa
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单例模式.Singleton@157ee3e5
    单M:

    单例模式咱们告一段落,下面将会NIO,在NIO有个所谓的观察者模式,说白了,就是事件驱动的。NIO叫做 new io ,也可叫no-blocking 就是非阻塞,还有的叫 Net io,就是网络加 io,他对以往的socket编程进行改进,同时IO函数进行改进,我们重点关注一下IO和网络编程,顺带着把观察者模式解决了,回去吧

    z:

  • 相关阅读:
    new delete的内部实现代码
    子串的替换
    求字符串的长度
    TSQL语句学习(四)
    TSQL语句学习(二)
    杭电acm1036
    杭电acm2032
    杭电acm2045
    杭电acm2072
    杭电acm1029
  • 原文地址:https://www.cnblogs.com/hansongjiang/p/3808219.html
Copyright © 2020-2023  润新知