python多執行緒中只初始化一次的單例模式

2021-10-23 18:09:26 字數 3108 閱讀 1779

python中的單例可以利用__new__和__init__來實現。每次建立例項的時候總會獲得同乙個例項,但是每次也會執行__init__方法。這就會造成單例中的屬性會被修改,更重要的是例項會被重新初始化。有時候我們並不希望再次初始化例項,我們希望直接獲得已經建立好的例項。應用類變數和鎖機制,可以實現需求。

import threading

from concurrent.futures.thread import threadpoolexecutor

class singleton:

_instance = none

def __new__(cls, *args, **kwargs):

if cls._instance is none:

cls._instance = super().__new__(cls)

return cls._instance

def __init__(self, num):

self.num = num

self.__init_flag = true

def get_name(self):

return self.num

def run_job(num):

obj = singleton(num)

print("thread:%s id:%s num:%s" % (num, id(obj), obj.num))

with threadpoolexecutor(max_workers=5) as pool:

for line in range(10):

pool.submit(run_job, line)

上面樣例的執行結果為。

thread:0 id:43341256 num:0

thread:1 id:43341256 num:1

thread:2 id:43341256 num:2

thread:3 id:43341256 num:3

thread:4 id:43341256 num:4

thread:5 id:43341256 num:5thread:6 id:43341256 num:6

thread:7 id:43341256 num:7

thread:8 id:43341256 num:8

thread:9 id:43341256 num:9

從結果中看到執行的10個執行緒中所建立的例項是同乙個,因為例項的 id 是相同的,所以例項物件所指的記憶體位址是同乙個,是同乙個例項。但是它們的屬性 num 是不同的,這是因為雖然例項是同乙個,記憶體位址也是乙個,但是每個例項都初始化了一遍(執行了一遍 __init__ 方法),初始化的時候對例項的屬性 num 值進行了覆蓋。

它們確確實實是同乙個例項,但是屬性值卻發生了改變。這就像是「乙個人」作為乙個例項,而這個人改了名字,本來叫「小小」,後來改名叫「大大」,不管叫啥他都是同乙個人。

有些時候我們建立乙個單例後並不想讓它修改屬性。我們想第一次建立例項完成後,第二次建立的時候直接返回單例,不要在去執行初始化方法,避免多次初始化帶來的資源和時間開銷。樣例**如下所示。

import threading

from concurrent.futures.thread import threadpoolexecutor

class singleton:

_lock_1 = threading.lock()

_lock_2 = threading.lock()

_instance = none

__init_flag = false

def __new__(cls, *args, **kwargs):

if cls._instance:

return cls._instance

with cls._lock_1:

if cls._instance is none:

cls._instance = super().__new__(cls)

return cls._instance

def __init__(self, num):

if self.__init_flag:

return

with self._lock_2:

if self.__init_flag:

return

self.num = num

self.__init_flag = true

def get_name(self):

return self.num

def run_job(num):

obj = singleton(num)

print("thread:%s id:%s num:%s" % (num, id(obj), obj.num))

with threadpoolexecutor(max_workers=10) as pool:

for line in range(50):

pool.submit(run_job, line)

# task =

# for i in range(10):

# t = threading.thread(target=run_job, args=(i,))

## for one in task:

# one.start()

## for one in task:

# one.join()

執行結果為。

thread:0 id:43669064 num:0

thread:1 id:43669064 num:0

thread:2 id:43669064 num:0

thread:3 id:43669064 num:0

thread:4 id:43669064 num:0

thread:5 id:43669064 num:0

thread:6 id:43669064 num:0

thread:7 id:43669064 num:0thread:8 id:43669064 num:0

thread:9 id:43669064 num:0

陣列 初始化 只含動態初始化 靜態初始化

首先j a中此處只講靜態初始化 動態初始化 靜態初始化就是提前在陣列中設定好了陣列內容,此內容不做改動,該多長已經在設定內容的時候已經決定 動態初始化就是僅限於new及確定陣列大小長度,裡面的陣列內容沒有,可自由進行填寫,也包含了靜態初始化的內容 示例 package 陣列 public class...

易語言多執行緒大漠多執行緒模板多執行緒初始化

多執行緒初始化,在啟動視窗後,需要首先呼叫,包括對執行緒控制代碼,視窗控制代碼,程序pid,程序狀態,異常狀態,是否暫停,是否結束的初始化,特別說明的是,為任務狀態申請記憶體空間,因為任務狀態的資料型別是文字型,防止避免多執行緒訪問文字型變數引發的資料衝突,預先分配好記憶體位址。511遇見易語言多執...

Python單例模式並且保證只被初始化一次

單例模式 假設我們有乙個日誌記錄器的類,現在我們不希望在每乙個需要寫入日誌的地方生成乙個日誌記錄器,那麼我們的做法是 如果已經在程式中存在乙個日誌記錄器,那麼就獲取它 如果不存在,則新建立乙個日誌記錄器。並且我們想保證 init 方法只執行一次 class singletonclass instan...