我已经在这个人身上追了好几天了,而且我疯了。我是一个非常业余的人,对蟒蛇来说是全新的,所以请原谅我的愚蠢。
我的主线程反复检查数据库中的条目,然后为它在数据库中找到的每个新条目启动线程。
它启动的线程基本上会轮询数据库中的某个值,如果它没有找到该值,它会做一些事情,然后它会休眠60秒并重新开始。
启动线程的简化非代码
while True:
stop = _Get_a_Value_From_Database_for_Exit() #..... a call to DBMS
If stop = 0:
Do_stuff()
time.sleep(60)
else:
break
在任何给定时间都可能有许多这些线程在运行。我想要做的是让主线程检查数据库中的另一个特定值的位置,然后可以在上面的示例中中断已启动的特定线程中的睡眠。目标是退出上面列出的特定线程,而不必等待睡眠持续时间的剩余时间。所有这些线程都可以由共享的数据库ID引用。我已经看到对 event.wait()
和 event.set()
的引用一直试图找出如何替换 time.sleep()
,但我不知道如何使用它来唤醒特定的线程而不是所有线程。
这是我无知的地方:有没有办法可以为event.wait创建基于数据库id
的东西(在启动的线程中像12345.wait(60)
一样12345.set()
在主线程中(所有动态都基于不断变化的数据库 id
)。
感谢您的帮助!!
答案 0 :(得分:2)
项目有点复杂,这是我的版本。
扫描数据库文件/tmp/db.dat
,预先填写两个单词
经理:为每个单词创建一个主题;默认是“威士忌”线程和“糖浆”线程
如果一个单词以_stop
结尾,如syrup_stop
,则通过设置其停止事件告诉该主题死亡
每个线程扫描数据库文件,如果它看到单词stop
则退出。如果设置了停止事件,它也会退出。
请注意,如果Manager线程设置了worker的stop_event,则worker将立即退出。每个线程都做了一些事情,但大部分时间花在stop_ev.wait()
调用上。因此,当事件确定时,它不必坐在那里,它可以立即退出。
服务器很有趣!启动它,然后通过向数据库添加行来向其发送命令。尝试以下各项:
$ echo pie >> /tmp/db.dat # start new thread
$ echo pie_stop >> /tmp/db.dat # stop thread by event
$ echo whiskey_stop >> /tmp/db.dat # stop another thread "
$ echo stop >> /tmp/db.dat # stop all threads
import logging, sys, threading, time
STOP_VALUE = 'stop'
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)-4s %(threadName)s %(levelname)s %(message)s",
datefmt="%H:%M:%S",
stream=sys.stderr,
)
class Database(list):
PATH = '/tmp/db.dat'
def __init__(self):
super(Database,self).__init__()
self._update_lock = threading.Lock()
def update(self):
with self._update_lock:
self[:] = [ line.strip() for line in open(self.PATH) ]
db = Database()
def spawn(events, key):
events[key] = threading.Event()
th = threading.Thread(
target=search_worker,
kwargs=dict(stop_ev=events[key]),
name='thread-{}'.format(key),
)
th.daemon = True
th.start()
def search_worker(stop_ev):
"""
scan database until "stop" found, or our event is set
"""
logging.info('start')
while True:
logging.debug('scan')
db.update()
if STOP_VALUE in db:
logging.info('stopvalue: done')
return
if stop_ev.wait(timeout=10):
logging.info('event: done')
return
def manager():
"""
scan database
- word: spawn thread if none already
- word_stop: tell thread to die by setting its stop event
"""
logging.info('start')
events = dict()
while True:
db.update()
for key in db:
if key == STOP_VALUE:
continue
if key in events:
continue
if key.endswith('_stop'):
key = key.split('_')[0]
if key not in events:
logging.error('stop: missing key=%s!', key)
else:
# signal thread to stop
logging.info('stop: key=%s', key)
events[key].set()
del events[key]
else:
spawn(events, key)
logging.info('spawn: key=%s', key)
time.sleep(2)
if __name__=='__main__':
with open(Database.PATH, 'w') as dbf:
dbf.write(
'whiskey\nsyrup\n'
)
db.update()
logging.info('start: db=%s -- %s', db.PATH, db)
manager_t = threading.Thread(
target=manager,
name='manager',
)
manager_t.start()
manager_t.join()
答案 1 :(得分:0)
相反,改变你的设计架构并进行分布式进程到进程的消息传递,而不是在无限循环中重复地追逐dbEngine,重复的dbSeek-s用于哑值,重新测试它一个不平等,然后试图杀死一个睡眠"。
在这种意义上, ZeroMQ
或 nanomsg
都是智能的,无代理的,消息传递层非常好。
渴望交火和水恕我直言,并没有为现实世界的系统带来任何好处。
智能,可扩展,分布式的流程到流程设计。
(关于简单的分布式流程到流程的消息/协调,图片由imatix / ZeroMQ提供)