基于Java利用static實(shí)現(xiàn)單例模式
一、之前舊的寫法
class Singleton{
? ? private Singleton() {}
? ? private static Singleton instance = null;
? ? public synchronized static Singleton getInstance() {
? ? ? ? ? ? if (instance == null) {
? ? ? ? ? ? ? ? instance = new Singleton();
? ? ? ? ? ? }
? ? ? ? ? ? return instance;
? ? ? ? }
}就利用Sington.getInstace就可以了,獲得的是同一個(gè)實(shí)例。
上面那個(gè)代碼有兩個(gè)優(yōu)點(diǎn):
- 懶加載,把在堆創(chuàng)建實(shí)例這個(gè)行為延遲到類的使用時(shí)。
- 鎖效果,防止生成多個(gè)實(shí)例,因?yàn)?code>synchronized修飾這個(gè)
static方法,所以相當(dāng)于給這個(gè)方法加上了一個(gè)類鎖??。
二、static代碼塊的效果
先來看一段代碼:
class StaticClass{
? ? private static int a = 1;
? ? static{
? ? ? ? System.out.println("語句1");
? ? ? ? System.out.println("語句2");
? ? }
? ? static{
? ? ? ? System.out.println("語句3");
? ? ? ? System.out.println("語句4");
? ? }
}當(dāng)在多個(gè)線程同時(shí)觸發(fā)類的初始化過程的時(shí)候(在初始化過程,類的static變量會(huì)被賦值為JVM默認(rèn)值并且static代碼塊會(huì)被執(zhí)行),為什么static不會(huì)被多次執(zhí)行?因?yàn)橛锌赡軆蓚€(gè)線程同時(shí)檢測到類還沒被初始化,然后都執(zhí)行static代碼塊,結(jié)果就把語句1234多打印了,為什么上述情況不會(huì)發(fā)生。
Thread thread1 = new Thread(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? Class.forName("StaticClass");//這一行觸發(fā)類的初始化導(dǎo)致靜態(tài)代碼塊執(zhí)行
? ? ? ? ? ? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? thread1.start();
? ? ? ? Thread thread2 = new Thread(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? Class.forName("StaticClass");//同樣
? ? ? ? ? ? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? });
? ? ? ? thread2.start();結(jié)果如下:
語句1
語句2
語句3
語句4
有一段英文對其進(jìn)行了解釋:
static initialization block can be triggered from multiple parallel threads (when the loading of the class happens in the first time), Java runtime guarantees that it will be executed only once and in thread-safe manner + when we have more than 1 static block - it guarantees the sequential execution of the blocks, 也就是說,java runtime幫我們做了兩件事:
- 在并行線程中,都出現(xiàn)了第一次初始化類的情況,保證類的初始化只執(zhí)行一次。
- 保證
static代碼塊的順序執(zhí)行
三、單例的另一種寫法
有了對static的知識的了解之后,我們可以寫出這樣的單例模式:
class Singleton{
? ? private Singleton() {}
? ? private static class NestedClass{
? ? ? ?static Singleton instance = new Singleton();//這條賦值語句會(huì)在初始化時(shí)才運(yùn)行
? ? }
? ? public static Singleton getInstance() {
? ? ? ? return NestedClass.instance;
? ? }
}- 懶加載,因?yàn)?code>static語句會(huì)在初始化時(shí)才賦值運(yùn)行,達(dá)到了懶加載的效果。
- 鎖??的效果由
Java runtime保證,虛擬機(jī)幫我們保證static語句在初始化時(shí)只會(huì)執(zhí)行一次。
四、總結(jié)
如果不知道static的基礎(chǔ)知識和虛擬機(jī)類加載的知識,我可能并不會(huì)知道這一種方法。理論永遠(yuǎn)先行于技術(shù),要學(xué)好理論才能從根本上提升自己。
到此這篇關(guān)于基于Java利用static實(shí)現(xiàn)單例模式的文章就介紹到這了,更多相關(guān)static實(shí)現(xiàn)單例模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決SpringBoot2.1.0+RocketMQ版本沖突問題
這篇文章主要介紹了解決SpringBoot2.1.0+RocketMQ版本沖突問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
SpringBoot中使用Zookeeper實(shí)現(xiàn)分布式鎖的案例
本文主要介紹了SpringBoot中使用Zookeeper實(shí)現(xiàn)分布式鎖的案例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01
java集合模擬實(shí)現(xiàn)斗地主洗牌和發(fā)牌
這篇文章主要為大家詳細(xì)介紹了java集合模擬實(shí)現(xiàn)斗地主洗牌和發(fā)牌,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
springboot后端如何實(shí)現(xiàn)攜帶token登陸
這篇文章主要介紹了springboot后端如何實(shí)現(xiàn)攜帶token登陸,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11
Java OpenCV圖像處理之仿射變換,透視變換,旋轉(zhuǎn)詳解
這篇文章主要為大家詳細(xì)介紹了Java OpenCV圖像處理中仿射變換,透視變換,旋轉(zhuǎn)的實(shí)現(xiàn),文中的示例代碼講解詳細(xì),快跟隨小編一起學(xué)習(xí)一下2022-10-10
Mybatis代碼生成器Mybatis Generator(MBG)實(shí)戰(zhàn)詳解
本文我們主要實(shí)戰(zhàn)Mybatis官方的代碼生成器:Mybatis Generator(MBG),掌握它以后,可以簡化大部分手寫代碼,我們只需要寫復(fù)雜邏輯代碼,需要的朋友可以參考下2023-05-05
Java從單體架構(gòu)升級到微服務(wù)要注意的一些問題
這篇文章主要介紹了Java從單體架構(gòu)升級到微服務(wù)要注意的一些問題,對架構(gòu)感興趣的同學(xué),可以參考下2021-04-04

