1)餓漢式
public class Person{
// 私有的構造方法
private Person{}
/* private Person person = new Person();
出現StackOverflowError錯誤 因為創建物件需要呼叫構造方法執行
構造方法執行在堆疊記憶體中 每次創建物件需要加載屬性 該屬性又是當前類物件
造成無限回圈創建物件 最終堆疊記憶體壓滿 不釋放
堆疊記憶體的空間比堆記憶體要小 所以堆疊記憶體先堆滿
因此需要加static修飾符 static修飾的元素屬于類 只加載一次
*/
//final 修飾的屬性基本型別是值不能改變 參考型別是地址不能改變 防止用戶拿到物件 將物件置為null
//私有的當前類物件作為屬性
private static final Person person = new Person();
// 公有的方法 用來獲取該類物件
/*
static 調該方法的兩種方式
1)類名點(方法需要static修飾)
2)物件點(該方法用來獲取當前類物件 此時還沒有物件)
*/
public static Person getPerson(){
return person;
}
}
2)雙重if檢測模型
public class Person{
// 私有構造方法
private Person{}
/*
valatile 修飾屬性 有以下幾個特點:
1. 屬性在某一個執行緒操作的時候 屬性是鎖定的 其他的執行緒沒法獲取屬性
2. 屬性被某一個執行緒修改后 另外的執行緒立即可見
3. 可以禁止指令重新排布
當被volatile修飾后 堆必須先分配一個物件記憶體 必須再將物件記憶體的地址交給堆疊參考 最后往物件空間中擺放東西
沒有volatile修飾時 可能會產生擺放東西時又來了一個物件 而此時并沒有將地址參考交給堆疊
*/
private static volatile Person person;
// 公有靜態方法 獲取該類物件
public static Person getPerson(){
if(person == null){
// 鎖定當前類
synchronized (Person.class){
// 鎖定時多執行緒并發 兩個執行緒經過第一次判斷都為null 當一個執行緒要鎖還沒鎖的時候 另一個執行緒卻鎖住了 new出了物件
// 而此時沒鎖住的那個執行緒這個時候再鎖 此時物件已經有了 所以需要再進行一次判斷
if(person == null){
person = new Person();
}
}
}
return person;
}
}
3)列舉實作單例
自由序列化、執行緒安全(列舉本身是執行緒安全的)
public enum Person{
PERSONONE;
public Person getInstance(){
return Person.PERSONONE;
}
}
4)static代碼塊實作單例模式
public class Person {
private Person(){}
private static final Person PERSON;
static {
PERSON = new Person();
}
public static Person getInstance(){
return PERSON;
}
}
5)靜態內部類實作
public class Person {
private Person(){}
private static class Holder{
private static final Person person = new Person();
}
public static Person getInstance(){
return Holder.person;
}
}
拓展
靜態內部類加載順序問題
public class Test {
public static void main(String[] args) {
new A.C();
//內部類靜態屬性p2 內部類靜態塊 內部類屬性p1 內部類屬性p3 內部類普通塊 內部類構造
}
}
class A {
private P p1 = new P("A類屬性p1");
static P p3 = new P("A類靜態屬性p2");
public A() {
System.out.println("A類構造方法");
}
private P p2 = new P("A類屬性p3");
static {
System.out.println("A類靜態塊");
}
{
System.out.println("A類普通塊");
}
public static class C {
private P p1 = new P("內部類屬性p1");
static P p2 = new P("內部類靜態屬性p2");
public C() {
System.out.println("內部類構造");
}
private P p3 = new P("內部類屬性p3");
static {
new P("內部類靜態塊");
}
{
new P("內部類普通塊");
}
}
}
class P {
public P(String s) {
System.out.println(s);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/242342.html
標籤:其他
下一篇:BMZ公開賽PWN題
