《Java多線程編程核心技術(shù)_高洪巖 著》讀后整理05

第5章 定時器Timer

  • 創(chuàng)建一個Timer就是啟動一個新的線程。

第6章 章例模式與多線程

如何使單例模式遇到多線程是安全的、正確的。

1.立即加載/“餓漢模式”
//在類初始化時就創(chuàng)建了靜態(tài)對象,不管以后使不使用都會占據(jù)一定內(nèi)存
public class Singleton {
    private Singleton(){}
    
    private static final Singleton instance = new Singleton();
    
    public static Singleton getInstance() {
        return instance;
    }
}
2.延遲加載/"懶漢模式"
//在第一次使用時實(shí)例化對象 Double-Check-Lock
//相傳在JDK1.5之前這個雙重檢查也是有問題的但之后修復(fù)了
public class Singleton {
    private Singleton(){}
    
    private static Singleton instance;
    
    public static Singleton getInstance() {
        if (instance == null)//避免加大塊鎖效率低
            synchronized (Singleton.class) {
                if (instance == null)//避免并發(fā)時的錯誤
                    instance = new Singleton();
            }
        return instance;
    }
}
3.靜態(tài)內(nèi)部類實(shí)現(xiàn)單例
public class Singleton {
    private Singleton(){}
    
    /*
     *1.此處要用到類中靜態(tài)屬性變量的特性:
     *  靜態(tài)變量屬于類并非對象,在類加載時就初始化完畢且就一次
     *2.因內(nèi)部內(nèi)類中的靜態(tài)的屬性,所以此內(nèi)部類需聲明成靜態(tài)內(nèi)部類(說明見下)
     *3.靜態(tài)內(nèi)部類在第一次使用時完成加載(說明見下)
     */
    private static class InnerSingleton {
        private static final Singleton instance = new Singleton();
    }   
    
    public static Singleton getInstance() {
        return InnerSingleton.instance;
    }
}

對上述第二條的解釋(來自互聯(lián)網(wǎng)):java類加載順序,首先加載類,執(zhí)行static變量初始化,接下來執(zhí)行對象的創(chuàng)建,如果我們要執(zhí)行代碼中的內(nèi)部類靜態(tài)變量的初始化,那么必須先執(zhí)行加載外部類,再加載內(nèi)部類,最后初始化內(nèi)部類中的靜態(tài)變量,問題就出在加載內(nèi)部類上面,我們可以把內(nèi)部類看成外部類的非靜態(tài)成員,它的初始化必須在外部類對象創(chuàng)建以后進(jìn)行,要加載內(nèi)部類必須在實(shí)例化外部類之后完成,java虛擬機(jī)要求所有的靜態(tài)變量必須在對象創(chuàng)建之前完成,這樣便產(chǎn)生了矛盾。

對上述第三條的解釋(來自互聯(lián)網(wǎng)):靜態(tài)內(nèi)部類的加載不需要依附外部類,在使用時才加載。不過在加載靜態(tài)內(nèi)部類的過程中也會加載外部類。靜態(tài)內(nèi)部類和非靜態(tài)內(nèi)部類一樣,都是在被調(diào)用時才會被加載。

4.靜態(tài)代碼塊實(shí)現(xiàn)單例
//靜態(tài)代碼塊中的代碼在使用類的時候就已經(jīng)執(zhí)行了,所以可以應(yīng)用這個特性來實(shí)現(xiàn)單例
public class Singleton {
    private Singleton(){}
    
    private static Singleton instance = null;
    
    static {
        instance = new Singleton();
    }
    
    public static Singleton getInstance() {
        return instance;
    }
}
5.枚舉實(shí)現(xiàn)單例
//enum類型的值實(shí)際上是通過在運(yùn)行期構(gòu)造出對象來表示的
//可以說使用的時候其實(shí)就是個已經(jīng)初始化好了的對象
public enum Singleton {
    INSTANCE
}

上述前四種在序列化對象再通過反序列化得到對象時得到的結(jié)果還是多例的,解決辦法如下:

//這就麻煩了,因?yàn)槿绻藛沃腥绻衅渌鼘ο蟮脑掃€得弄成transient的
protected Object readResolve() throws ObjectStreamException {
      return someInstance;//單例對象
}

但枚舉類型單例不存在序列化這個問題


第7章 拾遺增補(bǔ)

  • 線程狀態(tài):NEW,RUNNABLE,TERMINATED,TIMED_WAITING,BLOCKED,WAITING
myThread.getState();
  • 線程組:可以指的管理線程或線程組對象,有效地對線程或線程組對象進(jìn)行組織。
ThreadGroup group = new ThreadGroup("Group_Name");//線程組
Thread t1 = new Thread(group, new Thread(...));//管理線程
  • 線程中出現(xiàn)異常的處理
public static void main(String[] args) {
    MyThread t1 = new MyThread();
    t1.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
        @Override
        publi void uncaughtException(Thread t, Throwable e) {
            //some logic
            e.printStackTrace();
        }
    }
    t1.start();
}
  • 方法setUncaughtExceptionHandler()是給指定線程對象設(shè)置的anip處理器。在Thread類中還可以使用setDefaultUncaughtExceptionHandler()方法對所有線程對象設(shè)置異常處理器。
public static void main(String[] args) {
    MyThread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandlert() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            //some logic
            e.printStrackTrace();
        }
    }
    
    MyThread t1 = new MyThread();
    t1.start();
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容