Java多執行緒--單例模式的五種實現
阿新 • • 發佈:2019-01-02
一、惡漢模式
在這個類還沒有使用到的時候就已經建立好了
public class Singleton{
/**
*類變數在類準備階段就初始化了然後放在<clinit>構造方法中,
*一旦外部呼叫了靜態方法,那麼就會初始化完成。
*/
private static Singleton instance = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
}
二、懶漢模式-非執行緒安全
在需要獲取Singleton物件的時候才去建立這個物件
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
三、懶漢模式-執行緒安全
當兩個執行緒同時執行到判斷這個Singleton的例項instance是否為空的時候,兩個執行緒都判斷為空,那麼這個時候就會返回兩個例項,這樣一來就不是單例模式了。因此我們想到在方法上進行加鎖。
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public synchronized static Singleton getInstance(){
if(instance == null ){
instance = new Singleton();
}
return instance;
}
}
這個方式的使得一個執行緒等待的時候過程,降低併發效能。因此想到使用下面的方法
四、懶漢模式-雙檢鎖
public class Singleton{
private static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
我們使用synchronized這個關鍵字將鎖住一個程式碼塊,一旦一個執行緒獲得了這個物件鎖,那麼另一個執行緒就只能等待。當一個執行緒構造例項完成以後,另一個執行緒就進入判斷條件會發現我們的例項初始化過了,不再為null。此時返回例項物件。
五、靜態內部類
惡漢模式利用虛擬機器載入類的特性初始化例項物件,而懶漢模式則是在類被使用的時候才會被初始化。靜態內部類,當我們的類在載入的時候不會執行,只是在類被外界使用的時候才會被初始化。因此這種方式既實現了延遲載入又實現了執行緒安全。(這裡會不會出現安全洩漏問題)
public class Singleton{
private static Singleton instance = null;
static{
instance = new Singleton();
}
private Singleton(){
}
public static Singleton getInstance(){
return Singleton.instance;
}
}
測試程式碼
package JingDongProgram;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class Test8 {
public static void main(String[] args){
Callable<Singleton> t1 = new Thread8();
FutureTask<Singleton> f1 = new FutureTask<Singleton>(t1);
Callable<Singleton> t2 = new Thread9();
FutureTask<Singleton> f2 = new FutureTask<Singleton>(t1);
new Thread(f1).start();
new Thread(f2).start();
}
}
class Thread8 implements Callable{
@Override
public Object call() throws Exception {
System.out.println(Singleton.getInstance());
return null;
}
}
class Thread9 implements Callable{
@Override
public Object call() throws Exception {
System.out.println(Singleton.getInstance());
return null;
}
}
輸出結果
JingDongProgram.Singleton@2410eb3b
JingDongProgram.Singleton@2410eb3b
六、列舉類
public enum Singleton{
INSTANCE;
}