單例模式java(單例模式java實現代碼)

本文目錄一覽:

什麼是Java單例模式啊?

樓主您好

java模式之單例模式:

單例模式確保一個類只有一個實例,自行提供這個實例並向整個系統提供這個實例。

特點:

1,一個類只能有一個實例

2,自己創建這個實例

3,整個系統都要使用這個實例

例: 在下面的對象圖中,有一個”單例對象”,而”客戶甲”、”客戶乙” 和”客戶丙”是單例對象的三個客戶對象。可以看到,所有的客戶對象共享一個單例對象。而且從單例對象到自身的連接線可以看出,單例對象持有對自己的引用。

Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。在很多操作中,比如建立目錄 數據庫連接都需要這樣的單線程操作。一些資源管理器常常設計成單例模式。

外部資源:譬如每台計算機可以有若干個打印機,但只能有一個Printer Spooler,以避免兩個打印作業同時輸出到打印機中。每台計算機可以有若干個通信端口,系統應當集中管理這些通信端口,以避免一個通信端口被兩個請求同時調用。內部資源,譬如,大多數的軟件都有一個(甚至多個)屬性文件存放系統配置。這樣的系統應當由一個對象來管理這些屬性文件。

一個例子:Windows 回收站。

在整個視窗系統中,回收站只能有一個實例,整個系統都使用這個惟一的實例,而且回收站自行提供自己的實例。因此,回收站是單例模式的應用。

兩種形式:

1,餓漢式單例類

public class Singleton {

private Singleton(){}

//在自己內部定義自己一個實例,是不是很奇怪?

//注意這是private 只供內部調用

private static Singleton instance = new Singleton();

//這裡提供了一個供外部訪問本class的靜態方法,可以直接訪問

public static Singleton getInstance() {

return instance;

}

}

2,懶漢式單例類

public class Singleton {

private static Singleton instance = null;

public static synchronized Singleton getInstance() {

//這個方法比上面有所改進,不用每次都進行生成對象,只是第一次

//使用時生成實例,提高了效率!

if (instance==null)

instance=new Singleton();

return instance; }

}

第二中形式是lazy initialization,也就是說第一次調用時初始Singleton,以後就不用再生成了。

JAVA單例模式的幾種實現方法

單例模式1:

public

class

singleton{

private

static

singleton

st

=

null;

private

singleton(){

}

public

static

singleton

getinstance(){

if(st

==

null){

st

=

new

singleton();

}

return

st;

}

}

單例模式2:

public

class

singleton{

private

static

singleton

st

=

new

singleton();

private

singleton(){

}

public

static

singleton

getinstance(){

return

st;

}

}

多線程1:

導入thread所在的包

public

class

mythread1

extends

thread{

public

void

run(){

xxxxx寫自己的代碼

}

}

多線程2

導入runnable所在的包

public

class

mythread2

implements

runnable{

public

void

run(){

xxxxx寫自己的代碼

}

}

另寫一個測試類,在main方法中這樣寫:

thread

t

=

new

mythread1();

或者

runnable

r

=

new

mythread2();

thread

t

=

new

thread(r);

單例模式的作用及創建方法

單例模式作為常見的設計模式之一,在java的項目開發中會時常的用到。Java Singleton模式即保證在JVM運行時,一個類Class只有一個實例存在。

單例模式有什麼好處呢?

最簡單的一個例子就是網站計數器的設計了。當我們想要統計當前網站的在線人數時,一個顯而易見的問題就是並發所帶來的線程安全問題,當我們對這個計數器(網站人數)在同一時刻進行操作,再保存計數時就會造成數據的混亂,後者覆蓋前者的結果。一種解決方案就是把這個計數器設置為唯一對象,所有人都必須共用同一份數據。

實現唯一對象最好的解決辦法就是讓類自己負責保存它的唯一實例,並且讓這個類保證不會產生第二個實例,同時提供一個讓外部對象訪問該實例的方法。自己的事情自己辦,而不是由別人代辦,這非常符合面向對象的封裝原則。

單例模式的三個特點:

只有在自身需要的時候才會行動,從來不知道及早做好準備。它在需要對象的時候,才判斷是否已有對象,如果沒有就立即創建一個對象,然後返回,如果已有對象就不再創建,立即返回。

該方法在多線程情況下有可能重複創建實例,以下是線程安全的懶漢模式

這種模式的缺點是加鎖造成了效率下降,並且在絕大部分情況下是不需要同步的。使用雙重檢驗鎖(DCL),只在第一次初始化的時候進行同步加鎖

該方式在類加載的時候就被實例化了。

這種方式同樣利用了classloder的機制來保證初始化instance時只有一個線程,它跟餓漢不同的是(很細微的差別):餓漢方式是只要Singleton類被裝載了,那麼instance就會被實例化(沒有達到lazy loading效果),而這種方式是Singleton類被裝載了,instance不一定被初始化。因為SingletonHolder類沒有被主動使用,只有顯式通過調用getInstance方法時,才會顯示裝載SingletonHolder類,從而實例化instance。

想象一下,如果實例化instance很消耗資源,我想讓它延遲加載,另外一方面,我不希望在Singleton類加載時就實例化,因為我不能確保Singleton類還可能在其他的地方被主動使用從而被加載,那麼這個時候實例化instance顯然是不合適的。這個時候,這種方式就顯得很合理。

關於類加載情況下單例模式,如果單例由不同的類裝載器裝入,那便有可能存在多個單例類的實例。假定不是遠端存取,例如一些servlet容器對每個servlet使用完全不同的類 裝載器,這樣的話如果有兩個servlet訪問一個單例類,它們就都會有各自的實例。修復的辦法是

如何在Java中實現單例模式?

單例模式1:

public

class

singleton{

private

static

singleton

st

=

null;

private

singleton(){

}

public

static

singleton

getinstance(){

if(st

==

null){

st

=

new

singleton();

}

return

st;

}

}

單例模式2:

public

class

singleton{

private

static

singleton

st

=

new

singleton();

private

singleton(){

}

public

static

singleton

getinstance(){

return

st;

}

}

多線程1:

導入thread所在的包

public

class

mythread1

extends

thread{

public

void

run(){

xxxxx寫自己的代碼

}

}

多線程2

導入runnable所在的包

public

class

mythread2

implements

runnable{

public

void

run(){

xxxxx寫自己的代碼

}

}

另寫一個測試類,在main方法中這樣寫:

thread

t

=

new

mythread1();

或者

runnable

r

=

new

mythread2();

thread

t

=

new

thread(r);

JAVA單例模式有哪些?

一、懶漢式單例

在類加載的時候不創建單例實例。只有在第一次請求實例的時候的時候創建,並且只在第一次創建後,以後不再創建該類的實例。

public

class

LazySingleton

{

/**

*

私有靜態對象,加載時候不做初始化

*/

private

static

LazySingleton

m_intance=null;

/**

*

私有構造方法,避免外部創建實例

*/

private

LazySingleton(){

}

/**

*

靜態工廠方法,返回此類的唯一實例.

*

當發現實例沒有初始化的時候,才初始化.

*/

synchronized

public

static

LazySingleton

getInstance(){

if(m_intance==null){

m_intance=new

LazySingleton();

}

return

m_intance;

}

}

二、餓漢式單例

在類被加載的時候,唯一實例已經被創建。

public

class

EagerSingleton

{

/**

*

私有的(private)唯一(static

final)實例成員,在類加載的時候就創建好了單例對象

*/

private

static

final

EagerSingleton

m_instance

=

new

EagerSingleton();

/**

*

私有構造方法,避免外部創建實例

*/

private

EagerSingleton()

{

}

/**

*

靜態工廠方法,返回此類的唯一實例.

*

@return

EagerSingleton

*/

public

static

EagerSingleton

getInstance()

{

return

m_instance;

}

}

**************************************************************************************

懶漢方式,指全局的單例實例在第一次被使用時構建;

餓漢方式,指全局的單例實例在類裝載時構建

**************************************************************************************

三、登記式單例

這個單例實際上維護的是一組單例類的實例,將這些實例存放在一個Map(登記薄)中,對於已經登記過的實例,則從工廠直接返回,對於沒有登記的,則先登記,而後返回。

public

class

RegSingleton

{

/**

*

登記薄,用來存放所有登記的實例

*/

private

static

Map

m_registry

=

new

HashMap();

//在類加載的時候添加一個實例到登記薄

static

{

RegSingleton

x

=

new

RegSingleton();

m_registry.put(x.getClass().getName(),

x);

}

/**

*

受保護的默認構造方法

*/

protected

RegSingleton()

{

}

/**

*

靜態工廠方法,返回指定登記對象的唯一實例;

*

對於已登記的直接取出返回,對於還未登記的,先登記,然後取出返回

*

@param

name

*

@return

RegSingleton

*/

public

static

RegSingleton

getInstance(String

name)

{

if

(name

==

null)

{

name

=

“RegSingleton”;

}

if

(m_registry.get(name)

==

null)

{

try

{

m_registry.put(name,

(RegSingleton)

Class.forName(name).newInstance());

}

catch

(InstantiationException

e)

{

e.printStackTrace();

}

catch

(IllegalAccessException

e)

{

e.printStackTrace();

}

catch

(ClassNotFoundException

e)

{

e.printStackTrace();

}

}

return

m_registry.get(name);

}

/**

*

一個示意性的商業方法

*

@return

String

*/

public

String

about()

{

return

“Hello,I

am

RegSingleton!”;

}

}

原創文章,作者:簡單一點,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/129467.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
簡單一點的頭像簡單一點
上一篇 2024-10-03 23:26
下一篇 2024-10-03 23:26

相關推薦

  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • Python字符串寬度不限制怎麼打代碼

    本文將為大家詳細介紹Python字符串寬度不限制時如何打代碼的幾個方面。 一、保持代碼風格的統一 在Python字符串寬度不限制的情況下,我們可以寫出很長很長的一行代碼。但是,為了…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Python基礎代碼用法介紹

    本文將從多個方面對Python基礎代碼進行解析和詳細闡述,力求讓讀者深刻理解Python基礎代碼。通過本文的學習,相信大家對Python的學習和應用會更加輕鬆和高效。 一、變量和數…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29

發表回復

登錄後才能評論