1. 程式人生 > >關於多執行緒在簡單的懶漢模式下執行緒安全問題的解決

關於多執行緒在簡單的懶漢模式下執行緒安全問題的解決

一個簡單的懶漢模式,例如:
public class SingleTonDemo {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SingleTon singleTong1=SingleTon.getInstance();
    SingleTon singleTong2=SingleTon.getInstance();
    System.out.println(singleTong1+" "+singleTong2);
}

}
//單例類——懶漢模式
class SingleTon{
private static SingleTon singleTon=null;

private SingleTon() {
    System.out.println("懶漢模式");
}

public static SingleTon getInstance(){
    if(singleTon==null){
        singleTon=new SingleTon();
    }
    return singleTon;
}

}
這樣單例類被呼叫的時候僅會提供一個例項,可是在運用上多執行緒後卻不一定了
程式碼如下:
public class SingleTonDemo {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    SingleTonThread STT=new SingleTonThread();
    Thread thread1=new Thread(STT);
    Thread thread2=new Thread(STT);
    thread1.start();
    thread2.start();
}

}
//執行緒類
class SingleTonThread implements Runnable{

//重寫run方法
@Override
public void run() {
    SingleTon.getInstance();
}

}

//單例類——懶漢模式
class SingleTon{
private static SingleTon singleTon=null;

private SingleTon() {
    System.out.println("懶漢模式");
}

public static SingleTon getInstance(){
    if(singleTon==null){
        singleTon=new SingleTon();
    }
    return singleTon;
}

}
這樣的情況下,執行會發現單例類提供了兩個例項,那麼這個單例模式就存在安全問題了,為了解決問題,只需要將單例類的getInstance方法做成同步程式碼塊即可

程式碼如下:
public static SingleTon getInstance(){
//多一層判斷,減少呼叫synchronized關鍵字的次數,提高程式碼效率
if (singleTon==null) {
//由於是在靜態方法內,所以無法使用this關鍵字鎖定當前類,所以使用class模板類物件
synchronized (SingleTon.class) {
if(singleTon==null){
singleTon=new SingleTon();
}
}
}
return singleTon;
}
這樣就不會出現懶漢模式建立多個例項的問題了

本人新手,如若有錯誤或需要改進的地方,還請各位大神指點。

相關推薦

關於執行簡單懶漢模式執行安全問題的解決

一個簡單的懶漢模式,例如: public class SingleTonDemo { public static void main(String[] args) { // TODO Aut

解決執行單例模式執行安全問題

DCL雙檢查鎖機制 public class MyConfig { private volatile static MyConfig myConfig = null;//volatile

JAVA單例(懶漢模式執行安全

JAVA中單例模式分為兩種 1、餓漢模式 2、懶漢模式 餓漢模式不存線上程安全問題; 而懶漢模式存線上程安全問題。詳見下文,來自網路: 單例的多執行緒執行緒安全問題的描述 通常的多執行緒的執行緒安全問題,往往被描述成"多執行緒共享執行緒例項變數" 但多執行緒下的例項變數如果

Hadoop本地執行模式執行官方案例(Grep和WordCount)

官方Grep案例 #1,在hadoop-2.7.2檔案下建立input資料夾 [[email protected] hadoop-2.7.2]$ mkdir input [[email protected] hadoop-2.7.2]$ ll 總用量 56 drwx

如何在無頭模式執行WebDriver?

如何在無頭模式下執行WebDriver?如果您的CI工具(例如Jenkins)不支援UI,則可能需要這樣做。 在無頭模式下執行WebDriver自動測試在測試執行速度和更輕鬆地整合到CI管道方面具有優勢。 下面,我們將使用PhantomJS和ChromeDriver以無頭模式執行Sel

如何在無頭模式執行WebDriver ?

如何在無頭模式下執行WebDriver?如果您的CI工具(例如Jenkins)不支援UI,則可能需要這樣做。 在無頭模式下執行WebDriver自動測試在測試執行速度和更輕鬆地整合到CI管道方面具有優勢。 下面,我們將使用PhantomJS和ChromeDriver以無頭模式執行Sel

redis使用管道和普通模式執行效率的對比

1 普通模式 $redis = new Redis;     $redis->connect("127.0.0.1","6379");     $redis->auth("123456");     for($i=0;$i<10000;$i++){   

Linux在命令列模式執行命令

Linux系統登入環境 在Linux預設的登入的模式中,主要分為兩種,一種是純文字介面的登入環境,另一種則是圖形介面的登入環境。 ●Linux預設提供6個終端介面來讓使用者登入,切換的方式為:[Ctrl]+[Alt]+[F1]~[F6]。系統會按[F1]~[

模式執行spark自帶例項SparkPi

此係統是ubuntu,spark版本是1.0.0(下載的不是原始碼,而是編譯好的,在我的其他文章裡有下載網盤地址),hadoop版本2.2.0,scala版本2.10.4 1.spark-sunbmit命令:spark1.0之前的版本執行自帶例子使用$SPARK_HOME/

MapReduce 程式在 Windows 本地模式執行報錯問題的解決

一、報錯資訊 第一種: Exception in thread "main" java.lang.RuntimeException: Error while running command to get file permissions : java.io.IOException: (n

unity3d 非執行模式執行指令碼

using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; [ExecuteInEditMode]//在非執行模式下也會執行,改指令碼是更改

關於:“無法序列化會話狀態。在“StateServer”或“SQLServer”模式下,ASP.NET 將序列化會話狀態物件,因此不允許使用無法序列化的物件或 MarshalByRef 物件。如果自定義會話狀態儲存在“Custom”模式下執行了類似的序列化

錯誤描述: 無法序列化會話狀態。在“StateServer”或“SQLServer”模式下,ASP.NET 將序列化會話狀態物件,因此不允許使用無法序列化的物件或 MarshalByRef 物件。如果

在除錯模式執行CCleaner

如果您需要檢視CCleaner(http://www.ccleaner.cc/)的故障排除活動的詳細日誌,那麼您可以在除錯模式下執行該軟體。 CCleaner除錯 當您選擇在除錯模式下執行CCleaner時,它會建立一個日誌檔案,其中將列出具有不同優先順序的資訊。列表中的訊息數取決於

Hadoop HA 模式執行spark 程式

   (1)將Hadoop的hdfs-site.xml 和core-site.xml檔案複製到spark/conf目錄下   (2)追加如下內容到 spark-defaults.conf檔案 spark.files file:///home/hadoop/spar

Java簡易人聊天室(cmd執行

思路: 1.首先建立伺服器監聽 ServerSocket server = new ServerSocket(5000); 監聽某個指定埠號是否有連線請求 2.客戶端發起請求,也就是new了一個Socket socket = new Socket(host,port); 想某個指定埠號發起請

scala在cmd模式執行檔案報:1: error: ';' expected but '.' found. scalac C:\hello.scala 錯誤

scala在cmd模式下執行檔案報<console>:1: error: ';' expected but '.' found.        scalac C:\hello.scala 錯誤: 具體見圖:             按照如下方式即可執行

如何在命令列模式執行帶包的java檔案

最近在學習java,但是看到包(package)一節的時候,不知道在命令列下該怎麼執行帶包的java檔案了,經過查資料才搞懂。 比如有以下程式: package com.test public class Hello{           public static voi

實現所有的執行一起等待某個事件的發生,當某個事件發生時,所有執行一起開始往執行

假設要統計EXCEL裡的各個Sheet裡的的資料,可以開多個執行緒分別統計各個Sheet,等各個執行緒都統計完成後再進行彙總,這個時候就要實現如題描述的情景。這裡舉例說明,為了簡化,只是模擬。 我們知道,java裡的join是指等待該執行緒終止,才繼續往下執行。“join”很

Linux screen模式執行檔案

linux screen下執行檔案 screen下執行檔案: screen → 執行 php ***.php > ***.log 退出執行介面: ctrl+A → D 實時檢視日誌檔案內容:

Gem5在全系統(FS)模式執行自己的測試程式

上一篇文章講了怎麼用Gem5構建和啟動FS模式,這一次想看看怎麼在模擬的環境中測試自己的程式. 我這裡還是用的上次提到的X86的環境,整體過程是以下幾個步驟: 1.掛載映象 ypf@ypf-PC:~/ws$ sudo mount -o,loop,o