"單例模式"-之Java,Android面試必問設計模式(3/9)
單例模式
下面給大家分享面試必問8大設計模式中的第三種:單例模式
大家如果被面試官問到單例模式,只需回答下面的內容,並分析其中的幾個關鍵點即可.
單例模式分兩類:
1.開發使用餓漢式
2.但是懶漢式是必須會寫的
要求解釋未加鎖版的缺陷,和解決方法(加鎖)-並解釋兩個判斷的用意
程式碼以及講解詳情:
/**
* 餓漢式
*/
class Sigleton_E {
//私有化,靜態物件,外界拿不到
private static final Sigleton_E s = new Sigleton_E();
//"私有化"建構函式,外界不能建立
private Sigleton_E() {
}
//提供公共,靜態的方法獲取例項,不管怎麼樣獲取的都是上面new好的
public static Sigleton_E getInstance() {
return s;
}
}
/**
* 懶漢式,注意需要解決執行緒安全問題
*/
class Sigleton_L {
//私有化,靜態物件,外界拿不到
private static Sigleton_L s = null;//先宣告引用,不建立
//"私有化"建構函式,外界不能建立
private Sigleton_L () {
}
//提供公共,靜態的方法獲取例項
public static Sigleton_L getInstance() {
if(s==null){
s = new Sigleton_L();
}
return s;
}
}
/**
* 改裝版,加上鎖
*/
class Sigleton_L_L {
//私有化,靜態物件,外界拿不到
private static Sigleton_L_L s = null;//先宣告引用,不建立
//"私有化"建構函式,外界不能建立
private Sigleton_L_L() {
}
//提供公共,靜態的方法獲取例項,+雙重判斷
public static Sigleton_L_L getInstance() {
//為空,單執行緒鎖住,第二次不為空就進不來了
if (s == null) {
synchronized (Sigleton_L_L.class) {
//還為空,就建立,
//1.多個執行緒的時候,如果s==null,同時多個進來,那麼碰到鎖,只能一個再進這層,為空就建立,建立完畢
//2.建立完畢後,s!=null,再到剛剛進到鎖面前的其他執行緒,再進來一個,發現不是null了,所以不建立
if (s == null) {
s = new Sigleton_L_L();
}
}
}
//不為空就返回第一次那個
return s;
}
}
//測試類:
public class Test {
public static void main(String[] args) {
/*--------------非多執行緒情況--------------*/
/*--------------餓漢式-----------------*/
Sigleton_E e1 = Sigleton_E.getInstance();//不能new而是通過公共方法獲取
Sigleton_E e2 = Sigleton_E.getInstance();
System.out.println(e1);
System.out.println(e2);//列印結果:是同一個物件,標準單例.
*--------------未改裝版懶漢式-----------------*/
Sigleton_L l1 = Sigleton_L.getInstance();
Sigleton_L l2 = Sigleton_L.getInstance();
System.out.println(l1);
System.out.println(l2);//列印結果:同一個物件,符合.
/*--------------改裝版懶漢式-----------------*/
Sigleton_L_L ll1 =Sigleton_L_L.getInstance();
Sigleton_L_L ll2 =Sigleton_L_L.getInstance();
System.out.println(ll1);
System.out.println(ll2);//發現兩個列印的是:是同一個物件
/*------------多執行緒版本--------------*/
}
}
列印結果:
--------------------餓漢式----------------------
[email protected]
[email protected]
--------------------未改裝版懶漢式----------------------
[email protected]
[email protected]
--------------------裝版懶漢式----------------------
[email protected]
[email protected]
下面我們來測試多執行緒情況下的問題:
- 首先餓漢式:
public class Single_E {
private static Single_E s = new Single_E();
private Single_E() {
}
public static Single_E getInstance() {
return s;
}
public static void main(String[] args) {
//開啟十個執行緒,方便看出物件的情況
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
Single_E s = Single_E.getInstance();
System.out.println(s);
}
}).start();
}
}
}
列印結果:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
全部一樣,證明餓漢式執行緒安全
- 未改裝版懶漢式:
public class Single_L {
private static Single_L s = null;
private Single_L() {
}
public static Single_L getInstance() {
//既然這裡是最容易出現的問題,那麼我們就在模擬
if (s == null) {
//一個執行緒進入後,先休眠,然後其他執行緒相繼進入if判斷語句
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//這樣就得到多個結果了
s = new Single_L();
}
return s;
}
public static void main(String[] args) {
//開啟十個執行緒,方便看出物件的情況
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
Single_L s = Single_L.getInstance();
System.out.println(s);
}
}).start();
}
}
}
列印結果:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
各個物件不同,說明"懶漢式"非再裝版執行緒不安全
- “改裝版懶漢式”
public class Single_L_L {
private static Single_L_L s = null;
private Single_L_L() {
}
public static Single_L_L getInstance() {
if (s == null) {
try {
//同樣模擬一個進來
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 加鎖
synchronized (Single_L_L.class) {
if (s == null) {
s = new Single_L_L();
}
}
}
return s;
}
public static void main(String[] args) {
// 開啟十個執行緒,方便看出物件的情況
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
Single_L_L s = Single_L_L.getInstance();
System.out.println(s);
}
}).start();
}
}
}
列印結果:
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
得出結論:"改裝版(加鎖版)的懶漢式"是執行緒安全的.
使用拓展
開發的時候我們經常用到很多工具類,絕大部分工具類都不會做成單例,那麼如果我想做成單例的話,一個類中的內部類和同級的外部類呼叫單例工具時將會只是一個單例,使用其中的方法將會是疊加的.所以一般工具類不做成單例,除非是設計資料方面細節問題.
下面舉兩個例子:
包下的Test1類:
public class Test1 {
public static void main(String[] args) {
/*--------------第一次使用工具--------------*/
SingleTool s = SingleTool.getInstance();
System.out.println("s1 = "+s);
s.add(123);
s.add(true);
s.add("abc");
s.sout();
/*--------------第二次使用工具--------------*/
SingleTool s2 = SingleTool.getInstance();
System.out.println("s2 = "+s2);
/*--------------"同一個程式中"另一類(內部類)裡再使用工具--------------*/
Test1_in.use();
/*--------------"同一個程式中"另一類(同級)再使用工具--------------*/
Test1_1.meth();
/*--------------"同包下"的類使用工具--------------*/
Test2.use();
}
//內部類
static class Test1_in {
static void use() {
SingleTool s = SingleTool.getInstance();
System.out.println("s3 = "+s);
s.sout();
}
}
}
//同級外部類
class Test1_1 {
static void meth() {
SingleTool s = SingleTool.getInstance();
System.out.println("s4 = "+s);
}
}
列印結果:
s1 = com.company.[email protected]
123
true
abc
s2 = [email protected]
s3 = [email protected]
123
true
abc
s4 = [email protected]
s : [email protected]
123
true
abc
OK
說明:一個類中呼叫了同個工具類中的各個類,使用的工具是一樣的(單例) ,換成非單例的就不一樣了.
包下的另一個Test2類:
public class Test2 {
public static void use(){
SingleTool s = SingleTool.getInstance();
System.out.println("s : "+s);
s.add("OK");
s.sout();
}
}
class My {
public static void main(String[] args) {
/*--------------"同級別類"用工具--------------*/
Test2.use();
/*--------------"自己類使用工具"--------------*/
SingleTool s = SingleTool.getInstance();
System.out.println(" s : 自己"+s);
s.sout();
}
}
列印結果:
s : [email protected]
OK
s : 自己[email protected]
OK
結論和上面一樣;除非不同的程式(有各自的main)呼叫單例,才不會是同一個物件(符合)
安卓拓展:
- (啟動後,各個頁面得到的單例都會是唯一一個)
- 1.如果介面曾經使用過單例工具,那麼即使這個頁面銷燬(沒有完全退出程式時),再次跳轉過去,將還會是原來的單例.
2.除非是棧底完全退出時銷燬,如”滑動預覽任務退出”“(返回鍵退到桌面不代表完全銷燬).
原理其實多個活動介面都是”相當於存在一個main中“,他們相當於一個類中”同級別的類”而已這樣就可以用過java剛才了例子來理解這些介面了.
相關推薦
"單例模式"-之Java,Android面試必問設計模式(3/9)
單例模式 下面給大家分享面試必問8大設計模式中的第三種:單例模式 大家如果被面試官問到單例模式,只需回答下面的內容,並分析其中的幾個關鍵點即可. 單例模式分兩類: 1.開發使用餓漢式 2.但是懶漢式是必須會寫的 要求解釋未加鎖版的缺陷,和解決
"工廠模式"-之Java,Android面試必問設計模式(1/9)
1.工廠方法模式:分三種 這是我給大家介紹的8個面試必問的設計模式的第一類:工廠模式.學完這8類必會的那麼面試就不會有什麼問題了,其餘的無非都是多型的演變.好的開始講解第一類: 1.普通工
"裝飾模式"-之Java,Android面試必問設計模式(6/9)
下面我們開始講到面試必問的第六種設計模式:裝飾模式 “裝飾模式** 概念: 為了給一個物件增加功能:一個介面,一個具體類實現了方法,為了拓展方法,增加一個”裝飾類”繼承介面,(裝飾類裡宣告
"Java基礎"-Java,Android面試必問部分
關於文章內容: 大家好,今天我打算整理並總結關於JAVA,Android的相關方面的技能點,主要分為: 1.java基礎板塊; 3.andoroid基礎板塊; 4.android高階板塊. 如果大家認真掌握好,那麼你就相當於有了兩年以上的開發經
面試被問設計模式?不要怕看這裡:單例模式
設計模式是老生常談的問題,有人工作多年卻對設計模式一竅不通,但是更多的人是懂一點點,但是不求甚解。其實這樣不好,暫且不說在工作中的應用,即便是在面試時,被面試官問到設計模式時一臉懵逼,是非常尷尬的事情。本文不廢話,不談大篇理論教學,只針對面試,給出設計模式的關鍵點,
"Fragment"-Android面試必問"精華技能點"彙總
Fragment技能點彙總總結: 目錄: 一.Fragment跟Activity如何傳值? 一.getActivity() 1.從Fragment獲取Ativity的資訊 2.就可以呼叫Ativity的方法了 二.setArgum
Java高階面試必問—Dubbo面試題彙總
1、預設使用的是什麼通訊框架,還有別的選擇嗎? 2、服務呼叫是阻塞的嗎? 3、一般使用什麼註冊中心?還有別的選擇嗎? 4、預設使用什麼序列化框架,你知道的還有哪些? 5、服務提供者能實現失效踢出是什麼原理? 6、服務上線怎麼不影響舊版本?
Java基礎面試必問
1.&與&&區別?&和&&都是邏輯運算子,都是判斷兩邊同時真則為真,否則為假;但是&&當第一個條件不成之後,後面的條件都不執行了,而&am
"Android Touch事件分發機制"-Android面試必問"精華技能點"彙總
目錄: 一.事件分發中的 onTouch 和 onTouchEvent 有什麼區別,又該如何使用? 1.onTouch方法: 是View的 OnTouchListener介面中定義的方法。 當一個View綁定了OnTouchLister後,當有
"Android 螢幕適配"-Android面試必問"精華技能點"彙總
目錄: 1. 螢幕適配的方式都有哪些? 1.1 方式之-dp 1.1.1 名詞解釋: 解析度 480*800,1280*720,表示畫素點的總和 px(pix)-畫素 是螢幕裡的最小單元 dpi-畫素密度 每英寸螢幕具有的
"Intent"-Android面試必問"精華技能點"彙總
Intent: 一.intent傳輸資料時,可以傳遞哪些型別的資料? (非常多) 1.java的常見資料型別和String和他們的陣列形式 2.還有bundle 3.還有實現了Serializable和Parcelable介面的物件 二
"Android中的動畫"-Android面試必問"精華技能點"彙總
一.Android中的動畫有哪幾類,它們的特點和區別是什麼? 根據谷歌官方文件,動畫分為3種: 1.幀動畫/影象動畫(Drawable Animation) 1.xml方式->配置一組圖片,動態播放 2.補間動畫(View A
面試被問設計模式?不要怕看這裡:觀察者模式
本系列: 上一篇中,我給大家詳細講解了一下工廠模式以及面試中可能會被問到的關鍵點,我們先來溫習溫習。 工廠模式的關鍵點: 一、工廠模式分為簡單工廠,工廠和抽象工廠 二、三種工廠的實現是越來越複雜的 三、簡單工廠通過構造時傳入的標識來生產產品,不同產品都在同一個工廠
面試被問設計模式?不要怕看這裡:工廠模式
上一篇中,我介紹了單例模式的關鍵點,掌握了這些關鍵點,面試被問到單例肯定就沒太大問題了,我們先來回顧一下: 單例設計模式的關鍵點 一.私有建構函式 二.宣告靜態單例物件 三.構造單例物件之前要加鎖(lock一個靜態的object物件,某些語言可以宣告同步執行,其實是
阿里JAVA開發面試常問問題總結3
Java集合類 Java的集合類都位於java.util包中,Java集合中存放的是物件的引用,而非物件本身。 Java集合主要分為三種類型: 1.Set(集):集合中的物件不按特定方式排序,並且沒有重複物件。它的有些實現類能對集合中的物件按特定方式排序。
【設計模式】Java中的23種設計模式與7大原則
Java中的23種設計模式與7大原則建立型模式 5抽象工廠模式(Abstract factory pattern): 提供一個介面, 用於建立相關或依賴物件的家族, 而不需要指定具體類.生成器模式(Bu
淺析Java中的23種設計模式之----單例模式
單例模式作為23種設計模式之一,有著它特定的需求場景,比如一些內部資料結構不需要發生變化的例項(一些工具類)。 單例模式的核心就是隻允許有一個該類的靜態例項,並且這個靜態例項必須由這個類自己對外提供,也就是說只能由這個類自己例項化自己。由於只允許這個類例項化自己,就意味著我
單例模式之JAVA實現--如何實現真正的安全單例模式
單例模式 什麼是單例模式 單例模式屬於管理例項的創造型型別模式。單例模式保證在你的應用種最多隻有一個指定類的例項。 單例模式應用場景 專案配置類 讀取專案的配置資訊的類可以做成單例的,因為只需要讀取一次,且配置資訊欄位一般比較多節省資源。通過這個單例的類,
java 單例模式之執行緒安全的餓漢模式和懶漢模式
單例模式 解決的問題:保證一個類在記憶體中的物件唯一性. 比如:多程式讀取一個配置檔案時,建議配置檔案封裝成物件。會方便操作其中資料,又要保證多個程式讀到的是同一個配置檔案物件, 就需要該配置檔案物件在記憶體中是唯一的。 如何保證物件唯一性呢? 思想: 1,不讓其他程式建立
大型Java進階專題(五) 設計模式之單例模式與原型模式
## 前言 今天開始我們專題的第四課了,最近公司專案忙,沒時間寫,今天抽空繼續。上篇文章對工廠模式進行了詳細的講解,想必大家對設計模式合理運用的好處深有感觸。本章節將介紹:單例模式與原型模式。本章節參考資料書籍《Spring 5核心原理》中的第一篇 Spring 內功心法(Spring中常用的設計模式)