天天看點

6.單例和threadLocal

文章目錄

  • ​​部落格概述​​
  • ​​具體代碼​​
  • ​​threadlocal​​
  • ​​單例模式​​
  • ​​餓漢式​​
  • ​​懶漢式​​
  • ​​靜态内部類​​
  • ​​雙重檢查鎖​​

部落格概述

本文對threalocal關鍵字和單例模式的正常騷操作進行了代碼示例,并且進行了一些自己個人角度了解的說明。

具體代碼

threadlocal

public class ConnThreadLocal {

  public static ThreadLocal<String> th = new ThreadLocal<String>();
  
  public void setTh(String value){
    th.set(value);
  }
  public void getTh(){
    System.out.println(Thread.currentThread().getName() + ":" + this.th.get());
  }
  
  public static void main(String[] args) throws InterruptedException {
    
    final ConnThreadLocal ct = new ConnThreadLocal();
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run() {
        ct.setTh("張三");
        ct.getTh();
      }
    }, "t1");
    
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          Thread.sleep(1000);
          ct.getTh();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }, "t2");
    
    t1.start();
    t2.start();
  }
  
}      

threadlocal是線程局部變量,是一種多線程間并發通路的解決方案。與sync加鎖的方式不同,threadlocal完全不提供鎖,而是使用空間換時間的手段,為每個線程提供變量的獨立副本,以保障線程安全。從性能上說,threadlocal不具有絕對的優勢,,在并發不是很高的時候,加鎖的性能會更好,但作為一套與鎖完全無關的線程安全解決方案,在高并發量或者競争激烈的場景,使用threadlocal可以一定程度上減少競争。這種無鎖的方案,一個線程使用一個變量的場景适用,一旦出現多線程讀取相同變量的業務邏輯,就不适用了。一些架構如struts,spring都使用了這種技術。使用了map對象,然後key是線程ID。對上面這個例子,th對象是互相不可見的。

單例模式

單例模式有正常的5種形态,餓漢式,懶漢式,雙重檢查鎖,靜态内部類,枚舉。這裡給出前四種的寫法。

餓漢式

在餓漢式中static變量會在類加載時初始化,此時也不會涉及多個線程對象通路該對象的問題,虛拟機保證隻會裝載一次這個類,肯定不會發生并發通路的問題 ,是以可以省略sync關鍵字。

package instance;

/**
 * @Auther: ;李澤
 * @Date: 2019/3/27 22:20
 * @Description:
 */
public class SingletonDemo1 {
    //類初始化的時候,立即加載這個對象(沒有延時加載的優勢),加載類時,天然是線程無關的。
    private static SingletonDemo1 instance = new SingletonDemo1();
    private SingletonDemo1(){

    }
    //方法沒有同步調用效率高
    public static SingletonDemo1 getInstance() {
        return instance;
    }
}      

懶漢式

package instance;

/**
 * @Auther: ;李澤
 * @Date: 2019/3/27 22:46
 * @Description:
 */
public class SingletonDemo2 {
    //類初始化的時候,立即加載這個對象(沒有延時加載的優勢),加載類時,天然是線程無關的。
    private static SingletonDemo2 instance = new SingletonDemo2();
    private SingletonDemo2(){

    }
    
    public synchronized static SingletonDemo2 getInstance() {
        return instance==null?new SingletonDemo2():instance;
    }
}      

靜态内部類

/**
 * @Auther: ;李澤
 * @Date: 2019/3/27 22:49
 * @Description:
 */
public class SingletonDemo3 {

    private static class Singleton{
        private static Singleton singleton = new Singleton();
    }

    public static Singleton getInstance() {
        return Singleton.singleton;
    }
}      

雙重檢查鎖

package instance;

/**
 * @Auther: ;李澤
 * @Date: 2019/3/27 22:51
 * @Description:
 */
public class SingletonDemo4 {
    private static SingletonDemo4 demo4;

    public static SingletonDemo4 getInstance() {
        if(demo4 == null){
            synchronized (SingletonDemo4.class){
                if (demo4 == null){
                    demo4 = new SingletonDemo4();
                }
            }
        }
        return demo4;
    }
}      

繼續閱讀