發(fā)布對象
- 發(fā)布對象 :使一個(gè)對象能夠被當(dāng)前范圍之外的代碼所使用
- 對象溢出: 一種錯(cuò)誤的發(fā)布。當(dāng)一個(gè)對象還沒有構(gòu)造完成時(shí)脏毯,就使它被其他線程所見(類的非私有方法返回對象的引用滴某、通過公有靜態(tài)變量發(fā)布對象)
安全發(fā)布對象
在對象初始化函數(shù)中初始化一個(gè)對象引用
將對象的引用保存到volatile類型域或者AtomicReference對象中
將對象的應(yīng)用保存到某個(gè)正確構(gòu)造對象的final類型域中
-
將對象的引用保存到一個(gè)由鎖保護(hù)的域中
1.懶漢模式 線程不安全
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.NotThreadSafe;
/**
* 單例
* 懶漢模式
* 單例的實(shí)例在第一次運(yùn)行的時(shí)候進(jìn)行創(chuàng)建
* 單線程下安全 乡翅,多線程下不安全
*/
@NotThreadSafe
public class SingletonExample1 {
/**
* 私有構(gòu)造函數(shù)
*/
private SingletonExample1(){
}
/**
* 單例對象
*/
public static SingletonExample1 instance= null;
/**
* 靜態(tài)的工廠方法
* @return
*/
public static SingletonExample1 getInstance(){
if(instance==null){
instance = new SingletonExample1();
}
return instance;
}
}
2.餓模式 線程安全
單例的實(shí)例在類裝載的時(shí)候進(jìn)行創(chuàng)建
餓漢模式可能會導(dǎo)致線程資源的浪費(fèi)
使用的時(shí)候注意的問題:
1.私有構(gòu)造函數(shù)在實(shí)現(xiàn)的時(shí)候沒有太多的處理剪个,不然會導(dǎo)致該類加載過慢秧骑,出現(xiàn)性能問題
2.在使用過程中存在實(shí)際調(diào)用,不然會導(dǎo)致資源浪費(fèi)
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 單例
* 餓漢模式
* 單例的實(shí)例在類裝載的時(shí)候進(jìn)行創(chuàng)建
* 餓漢模式可能會導(dǎo)致線程資源的浪費(fèi)
* 使用的時(shí)候注意的問題:
* 1.私有構(gòu)造函數(shù)在實(shí)現(xiàn)的時(shí)候沒有太多的處理扣囊,不然會導(dǎo)致該類加載過慢乎折,出現(xiàn)性能問題
* 2.在使用過程中存在實(shí)際調(diào)用,不然會導(dǎo)致資源浪費(fèi)
*/
@ThreadSafe
public class SingletonExample2 {
/**
* 私有構(gòu)造函數(shù)
*/
private SingletonExample2(){
}
/**
* 單例對象
*/
public static SingletonExample2 instance= new SingletonExample2();
/**
* 靜態(tài)的工廠方法
* @return
*/
public static SingletonExample2 getInstance(){
return instance;
}
}
3.懶漢模式 引入靜態(tài)方法鎖 線程安全
單例的實(shí)例在第一次運(yùn)行的時(shí)候進(jìn)行創(chuàng)建
不推薦如暖,因?yàn)橹苯右雽ο箧i導(dǎo)致效率低
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.NotRecommend;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 單例
* 懶漢模式
* 單例的實(shí)例在第一次運(yùn)行的時(shí)候進(jìn)行創(chuàng)建
*/
@ThreadSafe
@NotRecommend
public class SingletonExample3 {
/**
* 私有構(gòu)造函數(shù)
*/
private SingletonExample3(){
}
/**
* 單例對象
*/
public static SingletonExample3 instance= null;
/**
* 靜態(tài)的工廠方法
* @return
*/
public static synchronized SingletonExample3 getInstance(){
if(instance==null){
instance = new SingletonExample3();
}
return instance;
}
}
4.懶漢模式 線程不安全
主要原因是JVM和CPU優(yōu)化笆檀,發(fā)生了指令重排
懶漢模式 -》 雙重同步鎖單例模式
單例的實(shí)例在第一次運(yùn)行的時(shí)候進(jìn)行創(chuàng)建
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.NotThreadSafe;
/**
* 單例
* 懶漢模式 -》 雙重同步鎖單例模式
* 單例的實(shí)例在第一次運(yùn)行的時(shí)候進(jìn)行創(chuàng)建
*/
@NotThreadSafe
public class SingletonExample4 {
/**
* 私有構(gòu)造函數(shù)
*/
private SingletonExample4(){
}
//1.memory = allocate() 分配對象的內(nèi)存空間
//2.ctorInstance() 初始化對象
//3.instance = memory 設(shè)置instance 指向剛分配的內(nèi)存
//jvm 和cpu優(yōu)化,發(fā)生了指令重排
//1.memory = allocate() 分配對象的內(nèi)存空間
//3.instance = memory 設(shè)置instance 指向剛分配的內(nèi)存
//2.ctorInstance() 初始化對象
/**
* 單例對象
*/
public static SingletonExample4 instance= null;
/**
* 靜態(tài)的工廠方法
* @return
*/
public static SingletonExample4 getInstance(){
//雙重檢測機(jī)制
if(instance==null){
//同步鎖
synchronized (SingletonExample4.class){
if(instance == null){
instance = new SingletonExample4();
}
}
}
return instance;
}
}
5.懶漢模式 引入volatile+雙重檢測機(jī)制禁止指令重拍使線程安全
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 單例
* 懶漢模式 -》 雙重同步鎖單例模式
* 單例的實(shí)例在第一次運(yùn)行的時(shí)候進(jìn)行創(chuàng)建
*/
@ThreadSafe
public class SingletonExample5 {
/**
* 私有構(gòu)造函數(shù)
*/
private SingletonExample5(){
}
//1.memory = allocate() 分配對象的內(nèi)存空間
//2.ctorInstance() 初始化對象
//3.instance = memory 設(shè)置instance 指向剛分配的內(nèi)存
/**
* 單例對象 volatile + 雙重檢測機(jī)制 -> 禁止指令重拍
*/
public volatile static SingletonExample5 instance= null;
/**
* 靜態(tài)的工廠方法
* @return
*/
public static SingletonExample5 getInstance(){
//雙重檢測機(jī)制
if(instance==null){
//同步鎖
synchronized (SingletonExample5.class){
if(instance == null){
instance = new SingletonExample5();
}
}
}
return instance;
}
}
6.餓漢模式 線程安全
靜態(tài)代碼塊
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 單例
* 餓漢模式
* 單例的實(shí)例在類裝載的時(shí)候進(jìn)行創(chuàng)建
* 餓漢模式可能會導(dǎo)致線程資源的浪費(fèi)
* 使用的時(shí)候注意的問題:
* 1.私有構(gòu)造函數(shù)在實(shí)現(xiàn)的時(shí)候沒有太多的處理盒至,不然會導(dǎo)致該類加載過慢,出現(xiàn)性能問題
* 2.在使用過程中存在實(shí)際調(diào)用,不然會導(dǎo)致資源浪費(fèi)
*/
@ThreadSafe
public class SingletonExample6 {
/**
* 私有構(gòu)造函數(shù)
*/
private SingletonExample6(){
}
/**
* 單例對象
*/
public static SingletonExample6 instance= null;
static {
instance = new SingletonExample6();
}
/**
* 靜態(tài)的工廠方法
* @return
*/
public static SingletonExample6 getInstance(){
return instance;
}
public static void main(String[] args) {
System.out.println(getInstance().hashCode());
System.out.println(getInstance().hashCode());
}
}
7.枚舉模式 線程安全 (最安全)
推薦使用
package com.qjx.concurrency.singleton;
import com.qjx.concurrency.annotations.Recommend;
import com.qjx.concurrency.annotations.ThreadSafe;
/**
* 單例
* 枚舉模式
* 最安全
*/
@ThreadSafe
@Recommend
public class SingletonExample7 {
/**
* 私有構(gòu)造方法
*/
private SingletonExample7 (){
}
public static SingletonExample7 getInstance(){
return Singleton.SINGLETON.getInstance();
}
/**
* 枚舉類定義單利實(shí)現(xiàn)
*/
private enum Singleton{
/**
* 枚舉單例
*/
SINGLETON;
private SingletonExample7 singleton;
/**
* JVM保證這個(gè)方法絕對只被調(diào)用一次
*/
Singleton(){
singleton = new SingletonExample7();
}
public SingletonExample7 getInstance(){
return singleton;
}
}
}