一、總線
總線是計算機各種功能部件或者設備之間傳送數據、控制信號等信息的公共通信解決方案之一。現假設有如下場景:某中央處理器(CPU)通過某種協議總線與一個信號燈相連,信號燈有64種顏色可以設置,中央處理器上運行着三個線程,都可以對這個信號燈進行控制,並且可以獨立設置該信號燈的顏色。抽象掉協議細節(用打印表示),如何實現線程對信號等的控制邏輯。
加線程鎖進行控制,無疑是最先想到的方法,但各個線程對鎖的控制,無疑加大了模塊之間的耦合。下面,我們就用設計模式中的單例模式,來解決這個問題。
什么是單例模式?單例模式是指:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。具體到此例中,總線對象,就是一個單例,它僅有一個實例,各個線程對總線的訪問只有一個全局訪問點,即惟一的實例。
Python代碼如下:
#encoding=utf8 import threading import time #這里使用方法__new__來實現單例模式 class Singleton(object):#抽象單例 def __new__(cls, *args, **kw): if not hasattr(cls, '_instance'): orig = super(Singleton, cls) cls._instance = orig.__new__(cls, *args, **kw) return cls._instance #總線 class Bus(Singleton): lock = threading.RLock() def sendData(self,data): self.lock.acquire() time.sleep(3) print "Sending Signal Data...",data self.lock.release() #線程對象,為更加說明單例的含義,這里將Bus對象實例化寫在了run里 class VisitEntity(threading.Thread): my_bus="" name="" def getName(self): return self.name def setName(self, name): self.name=name def run(self): self.my_bus=Bus() self.my_bus.sendData(self.name) if __name__=="__main__": for i in range(3): print "Entity %d begin to run..."%i my_entity=VisitEntity() my_entity.setName("Entity_"+str(i)) my_entity.start()
運行結果如下:
Entity 0 begin to run...
Entity 1 begin to run...
Entity 2 begin to run...
Sending Signal Data... Entity_0
Sending Signal Data... Entity_1
Sending Signal Data... Entity_2
在程序運行過程中,三個線程同時運行(運行結果的前三行先很快打印出來),而后分別占用總線資源(后三行每隔3秒打印一行)。雖然看上去總線Bus被實例化了三次,但實際上在內存里只有一個實例。
二、單例模式
單例模式是所有設計模式中比較簡單的一類,其定義如下:Ensure a class has only one instance, and provide a global point of access to it.(保證某一個類只有一個實例,而且在全局只有一個訪問點)
三、單例模式的優點和應用
單例模式的優點
1、由於單例模式要求在全局內只有一個實例,因而可以節省比較多的內存空間;
2、全局只有一個接入點,可以更好地進行數據同步控制,避免多重占用;
3、單例可長駐內存,減少系統開銷。
單例模式的應用舉例
1、生成全局惟一的序列號;
2、訪問全局復用的惟一資源,如磁盤、總線等;
3、單個對象占用的資源過多,如數據庫等;
4、系統全局統一管理,如Windows下的Task Manager;
5、網站計數器。
四、單例模式的缺點
1、單例模式的擴展是比較困難的;
2、賦於了單例以太多的職責,某種程度上違反單一職責原則(六大原則后面會講到);
3、單例模式是並發協作軟件模塊中需要最先完成的,因而其不利於測試;
4、單例模式在某種情況下會導致“資源瓶頸”。