#!python
# -*- coding:utf-8 -*-
# 場景:
# 目的:經過單例實現客戶端調用sdk時,sdk中的方法對客戶端數據的批處理
# 參考:
# {
# Python單例模式(Singleton)的N種實現 - 知乎
# https://zhuanlan.zhihu.com/p/37534850
# 設計模式(Python)-單例模式 - 簡書
# https://www.jianshu.com/p/ec6589e02e2f
# http://xiaorui.cc/2016/04/10/python多線程下保持單例模式的實例惟一/
# PythonDecoratorLibrary - Python Wiki
# https://wiki.python.org/moin/PythonDecoratorLibrary
# 3. Data model — Python 3.7.3 documentation
# https://docs.python.org/3/reference/datamodel.html#object.__new__
# 8.10. Queue — A synchronized queue class — Python 2.7.16 documentation
# https://docs.python.org/2/library/queue.html
# The Queue class in this module implements all the required locking semantics.
# 3. Data model — Python 3.7.3 documentation
# https://docs.python.org/3/reference/datamodel.html#specialnames
# 3. Data model — Python 3.7.3 documentation
# https://docs.python.org/3/reference/datamodel.html#object.__del__
# }
# 注意:
# 線程安全
# 實例析構、類的析構
# 須要測試:
# 一、線程安全
# 二、效率
# TODO 類的析構
import threading
def make_synchronized(func):
func.__lock__ = threading.Lock()
def synced_func(*args, **kws):
with func.__lock__:
return func(*args, **kws)
return synced_func
class SdkSingletonBatchHandler(object):
__instance = None
# 存放批處理的隊列 批處理方法對其按照先進先出FIFO處理
queueContainer = []
queueLength = None
batchHandlerFunc = None
# 隊列生存時間
timeToLiveSeconds = 0.5
__bornTime = 0
@make_synchronized
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__bornTime = time.time()
cls.__instance = object.__new__(cls, *args, **kwargs)
if cls.queueLength is None:
cls.queueLength = 10
cls.batchAction()
return cls.__instance
@classmethod
def batchHandler(cls, queueContainer):
return cls.batchHandlerFunc
@classmethod
def batchAction(cls):
if len(cls.queueContainer) >= cls.queueLength or cls.timeToLiveSeconds < time.time() - cls.__bornTime:
cls.batchHandler(cls.queueContainer)
cls.queueContainer = []
cls.__bornTime = time.time()
@classmethod
def diyClassDestruct(cls):
# Python 2.7.5 自定義類的析構函數,注意不是實例的析構函數
if len(cls.queueContainer) > 0:
cls.batchHandler(cls.queueContainer)
def __del__(self):
# Python 2.7.5 實例的析構函數
# 實際測試發現無效
if len(self.queueContainer) > 0:
self.batchHandler(self.queueContainer)
import time
def bizFuncNotBatch(param):
time.sleep(0.02)
print "do sth" + str(param)
def bizFuncBatch(param):
def batchHandler(paramList):
for i in paramList:
pass
time.sleep(0.02)
print "do sth" + str(paramList)
s = SdkSingletonBatchHandler()
s.__class__.queueLength = 200
s.__class__.timeToLiveSeconds = 123
s.__class__.batchHandlerFunc = batchHandler
s.__class__.queueContainer.append(param)
s.__class__.batchAction()
print "do sth Batch"
# return 測試所需對象id
return s
# 測試
# 線程安全
def testThreadSafeWorker():
s1 = bizFuncBatch("param")
s2 = bizFuncBatch("param")
print "id1={},id2={}".format(id(s1), id(s2))
task = []
for i in range(300):
t = threading.Thread(target=testThreadSafeWorker())
task.append(t)
for i in task:
i.start()
for i in task:
i.join()
# 測試
# 效率
data = [{'i': i, 'v': "value"} for i in range(20)]
consoleInfo = []
def consoleInfoHub(*args):
global consoleInfo
s = ("{}" + time.ctime() + " " + str(time.time())).format(args[0])
consoleInfo.append(s)
consoleInfoHub("notBatch:Start:")
for i in data:
bizFuncNotBatch(i)
consoleInfoHub("notBatch:End:")
consoleInfoHub("Batch:Start:")
for i in data:
bizFuncBatch(i)
consoleInfoHub("Batch:End:")
for i in consoleInfo:
print i
class TestClassDel(object):
__instance = None
def __init__(self):
print("init")
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = object.__new__(cls, *args, **kwargs)
return cls.__instance
def __del__(self):
print(1)
s1 = TestClassDel()
s2 = TestClassDel()
del s1
del s2
init
init
1html
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32python
class TestClassDel(object):
__instance = None
def __init__(self):
print "init"
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = object.__new__(cls, *args, **kwargs)
return cls.__instance
def __del__(self):
print 1
s1 = TestClassDel()
s2 = TestClassDel()
del s1
del s2
Python 2.7.5 (default, May 15 2013, 22:44:16) [MSC v.1500 64 bit (AMD64)] on win32設計模式
init
init安全
沒有打印1多線程
注意以上爲單例模式 app
class TestClassDel(object):
__instance = None
def __init__(self):
print "init"
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = object.__new__(cls, *args, **kwargs)
return cls.__instance
def __del__(self):
print 1
s1 = TestClassDel()
s2 = TestClassDel()
del s1
del s2
class T():
def __call__(self, *args, **kwargs):
print 1
d=T().__call__()
打印1受此啓發【注意 目標環境爲python2.7.5】