本文目錄一覽:
什麼是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-tw/n/129467.html