1. 程式人生 > >java單例設計模式

java單例設計模式

返回 線程 clas pub 問題: private 利用 線程安全 run

什麽是單例設計模式

單例即只有一個實例,該模式的作用是保證程序中某個類的對象只有一個。

單例模式分為懶漢式和餓漢式。

懶漢式

class Student{
	static Student st;
	private Student(){}
	public static Student getInstance(){
		//引用數據類型屬性在內存中的默認值為null
		//如果值為null 只創建一次對象
		if(st==null){
			st = new Student();
		}
		return st;
	}
}

public class Test1 {
	
	public static void main(String[] args) {
		// 利用hascode 相等 是單例  
		Student tes1 = Student.getInstance();
		System.out.println(tes1.hashCode());
		
		Student tes2 = Student.getInstance();
		System.out.println(tes2.hashCode());
	}
}

以上可以看出結果的hasCode值是相同的只創建了一個對象

技術分享圖片

但是這種模式在多線程的情況下會產生線程安全問題:

class Teacher{
	static Teacher s;
	private Teacher(){}
	public static Teacher getInstance(){
		if(s == null){
			s = new Teacher();
		}
		return s;
	}
}

class StudentThread extends Thread{
	public void run(){
		for(int i = 0;i<3;i++){
				Teacher ss = Teacher.getInstance();
				System.out.println(ss.hashCode());
		}
	}
}

public class Test2 {
	public static void main(String[] args) {
		//單例模式在多線程中存在線程安全問題  需要解決線程安全
		//創建線程
		StudentThread tt1 = new StudentThread();
		StudentThread tt2 = new StudentThread();
		//就緒狀態
		tt1.start();
		tt2.start();
	}
}

如果在運行多次的情況下會出現hasCode不一定都一樣 這就出現了線程安全問題:

技術分享圖片

解決辦法只需要將返回對象的方法設置為同步方法即可

public synchronized static Teacher getInstance(){
		if(s == null){
			s = new Teacher();
		}
		return s;
	}

餓漢式

//餓漢式
class Hangle{
	//創建靜態屬性的時候就賦值  並且只執行一次  也就是說只創建一次對象
	static Hangle ha = new Hangle();
	public static Hangle getInstance(){
		return ha;
	}
}

class SingleThread extends Thread{
	public void run(){
		for(int i = 0;i<4;i++){
			Hangle hh = Hangle.ha;
			System.out.println(hh.hashCode());
		}
	}
}

public class Test3 {
	public static void main(String[] args) {
		SingleThread tt1 = new SingleThread();
		SingleThread tt2 = new SingleThread();
		
		//就緒狀態
		tt1.start();
		tt2.start();
		
		// 總結: 懶漢式 在多線程環境中會發生線程安全問題 (可以解決線程問題)
		//而餓漢式不管是在單線程還是在多線程中 不存在線程安全問題  建議定義單例模式的話 用餓漢式
		//餓漢式單例模式要比懶漢式效率高
	}
}

java單例設計模式