java多線程編程學習chapter6

單例模式和多線程

解決問題:如何使單例模式遇到多線程是安全的,正確的

1.立即加載/餓漢模式
在方法調用前,實例已經創建好
package com.nineclient.call.chapter6.singleton;

public class Run1 {

	public static void main(String[] args) {
		ThreadA a1 = new ThreadA();
		ThreadA a2 = new ThreadA();
		ThreadA a3 = new ThreadA();
		a1.start();
		a2.start();
		a3.start();
		
	}
	
}

class ThreadA extends Thread {
	public void run() {
		System.out.println(MyService.getMyService().hashCode());
	}
}

class MyService {
	private static MyService service = new MyService();
	
	private MyService(){
		
	}
	
	public static MyService getMyService() {
		return service;
	}

}

2.延遲加載/懶漢模式
調用方法時,實例已經創建好
package com.nineclient.call.chapter6.singleton;

public class Run2 {

	public static void main(String[] args) {
		Thread1 a = new Thread1();
		a.start();
		/*Thread1 a1 = new Thread1();
		a1.start();
		Thread1 a2 = new Thread1();
		a2.start();*/
	}
}

class MyService1 {
	private static MyService1 service;
	private MyService1(){}
	public static MyService1 getMyService1() {
		if(service == null) {
			service = new MyService1();
		}
		return service;
	}
}

class Thread1 extends Thread {
	public void run() {
		System.out.println(MyService1.getMyService1().hashCode());
	}
}

當多線程的時候,取得值有可能會不一樣

3.延遲加載的解決方案
就是在get方法上加上synchronized
package com.nineclient.call.chapter6.singleton;

public class Run3 {

	public static void main(String[] args) {
		Thread2 a = new Thread2();
		a.start();
		Thread2 a1 = new Thread2();
		a1.start();
		Thread2 a2 = new Thread2();
		a2.start();
	}
}

class MyService2 {
	private static MyService2 service;
	private MyService2(){}
	public synchronized static MyService2 getMyService2() {
		if(service == null) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			service = new MyService2();
		}
		return service;
	}
}

class Thread2 extends Thread {
	public void run() {
		System.out.println(MyService2.getMyService2().hashCode());
	}
}

這種情況在要求效率比較高的時候,可以使用同步代碼塊
package com.nineclient.call.chapter6.singleton;

public class Run4 {

	public static void main(String[] args) {
		Thread4 a = new Thread4();
		a.start();
		Thread4 a1 = new Thread4();
		a1.start();
		Thread4 a2 = new Thread4();
		a2.start();
	}
}

class MyService4 {
	private static MyService4 service;
	private MyService4(){}
	public static MyService4 getMyService4() {
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		synchronized (MyService4.class){
			if(service == null) {
			    service = new MyService4();
			}
		}
			
		return service;
	}
}

class Thread4 extends Thread {
	public void run() {
		System.out.println(MyService4.getMyService4().hashCode());
	}
}

4.使用靜態內置類實現單例模式
package com.nineclient.call.chapter6.singleton;

public class Run5 {
	public static void main(String[] args) {
		Thread5 a = new Thread5();
		a.start();
		Thread5 a1 = new Thread5();
		a1.start();
		Thread5 a2 = new Thread5();
		a2.start();
	}

}

class MyService5 {
	private static class MyService5Handle{
		private static MyService5 service = new MyService5();
	}
	private MyService5() {
		
	}
	
	public static MyService5 getMyService5() {
		return MyService5Handle.service;
	}
	
}

class Thread5 extends Thread {
	public void run() {
		System.out.println(MyService5.getMyService5().hashCode());
	}
}

5.如果是序列化對象,默認方式運行,還是會出現多例
解決辦法是在反序列化中使用readResolve()方法

6.使用靜態代碼塊實現單例模式
package com.nineclient.call.chapter6.singleton;

public class Run6 {

	public static void main(String[] args) {
		Thread6 a = new Thread6();
		a.start();
		Thread6 b = new Thread6();
		b.start();
		Thread6 c = new Thread6();
		c.start();
		
	}
}

class MyService6 {

	private static MyService6 service;
	private MyService6() {
		
	}
	static {
		service = new MyService6();
	}
	public static MyService6 getMyService() {
		return service;
	}

}

class Thread6 extends Thread{
	public void run() {
		System.out.println(MyService6.getMyService().hashCode());
	}
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章