我有多个线程来构造一个参数化的对象,并在其上调用start和stop。问题是,每个参数的基础服务应该只在第一次启动时启动,并且只在最后一次停止时停止一次。我尝试了以下方法:
# /usr/bin/env python3
import multiprocessing.pool
import random
import threading
import time
import uuid
def log(args):
print(f"{threading.get_ident()}: {args}")
class Myobj:
lock = threading.Lock()
count = 0
def __init__(self, name: str):
self.name = name
def log(self, args):
log(f"{self.name}: {args}")
def start(self):
with self.lock:
self.count += 1
if self.count == 1:
self.value = uuid.uuid1()
self.log(f"starting {self.value}")
self.log(f"ref up {self.count}")
def stop(self):
with self.lock:
self.count -= 1
if self.count == 0:
self.log(f"stopping {self.value}")
self.log(f"ref down {self.count}")
def thread(i):
# references service with specific name
myobj = Myobj(f"name{i % 2}")
# only the first thread that gets here should start the service with that name
myobj.start()
# some_computation()
time.sleep(random.uniform(0, 2))
# only the last thread that gets here should stop the service with that name
myobj.stop()
size = 6
with multiprocessing.pool.ThreadPool(size) as tp:
tp.map(thread, range(size))
字符串
但是,计数器不是唯一的:
140385706604224: name0: starting ab142d3c-2ebd-11ee-9d78-901b0e12b878
140385706604224: name0: ref up 1
140385698211520: name1: starting ab143264-2ebd-11ee-a67e-901b0e12b878
140385698211520: name1: ref up 1
140385689818816: name0: starting ab1435fc-2ebd-11ee-99f3-901b0e12b878
140385689818816: name0: ref up 1
140385681426112: name1: starting ab1439b2-2ebd-11ee-932c-901b0e12b878
140385681426112: name1: ref up 1
140385673033408: name0: starting ab143d36-2ebd-11ee-9959-901b0e12b878
140385673033408: name0: ref up 1
140385664640704: name1: starting ab1443f8-2ebd-11ee-a1b9-901b0e12b878
140385664640704: name1: ref up 1
140385673033408: name0: stopping ab143d36-2ebd-11ee-9959-901b0e12b878
140385673033408: name0: ref down 0
140385706604224: name0: stopping ab142d3c-2ebd-11ee-9d78-901b0e12b878
140385706604224: name0: ref down 0
140385689818816: name0: stopping ab1435fc-2ebd-11ee-99f3-901b0e12b878
140385689818816: name0: ref down 0
140385681426112: name1: stopping ab1439b2-2ebd-11ee-932c-901b0e12b878
140385681426112: name1: ref down 0
140385664640704: name1: stopping ab1443f8-2ebd-11ee-a1b9-901b0e12b878
140385664640704: name1: ref down 0
140385698211520: name1: stopping ab143264-2ebd-11ee-a67e-901b0e12b878
140385698211520: name1: ref down 0
型
理想情况下,我应该看到name0
和name1
开始和停止行打印一次,如下所示,服务name0
和服务name1
启动,然后停止。name0
和name1
服务之间的顺序无关。所以只能输出如下所示:
140385706604224: name0: starting ab142d3c-2ebd-11ee-9d78-901b0e12b878
140385698211520: name1: starting ab143264-2ebd-11ee-a67e-901b0e12b878
140385681426112: name0: stopping ab142d3c-2ebd-11ee-9d78-901b0e12b878
140385664640704: name1: stopping ab143264-2ebd-11ee-a67e-901b0e12b878
型
什么是一个好的设计来实现这样一个类,它可以启动和停止具有多个线程的唯一命名服务?这可以作为泛型类实现吗?
1条答案
按热度按时间fnatzsnv1#
只要让计数器变成一个可变对象,它就应该按照你想要的方式运行。
现在,类变量
count
是一个int
,一个不可变类型。如果这是一个可变类型,那么它将按照您所期望的方式在示例之间共享它的值。字符串
但是如果你使用一个可变对象,比如
collections.Counter
,这就像你所期望的那样工作:型
将此应用于您的场景:
的字符串