1

我对 Python 编程相当陌生,线程不是我的专业领域。我有一个问题,我希望这里的人可以帮助我。

任务:作为我硕士论文的一部分,我需要制作一个涉及多人游戏的混合现实游戏。在我的游戏设计中,每个玩家可以设置一堆陷阱,每个陷阱在特定的时间段内都处于活动状态,例如 30 秒。为了在所有玩家之间保持一致的游戏状态,需要在服务器端进行所有时间检查,这是用 Python 实现的。

我决定启动一个 python 线程,每次玩家放置一个新的陷阱并在线程上运行一个计时器。所有这部分都很好,但是当我需要通知主线程这个特定陷阱的时间到了时,真正的问题就出现了,这样我就可以与客户端(android 设备)进行通信。

我尝试在任务完成后创建一个队列并将信息插入队列,但我不能做一个 queue.join() 因为它会暂停主线程直到任务完成,这不是我需要的,也不是在我的情况下它是理想的,因为主线程一直在与客户端通信,如果它被停止,那么与玩家的所有通信都将停止。

我需要运行计时器的辅助线程来告诉主线程,一旦时间用完,时间已经用完并发送陷阱的ID,以便我可以将此信息传递给android客户端删除它。我怎样才能做到这一点?

关于如何在不启动大量线程的情况下完成此任务的任何其他建议,也欢迎提出.. :) :)

在此先感谢您的帮助..

干杯

4

3 回答 3

2

我终于找到了一个用python编写的漂亮的小任务调度程序,它实际上非常轻巧,非常方便使用回调机制为以后的时间或日期安排事件,它允许子线程将值传回主线程通知主线程其状态以及作业是否成功完成。

那些需要与问题中的人类似的功能并且不想与线程讨价还价的人可以使用此调度程序来安排他们的事件并在事件完成时获得回调

这是APScheduler的链接

于 2012-06-21T12:18:33.677 回答
1

It may be easier to have the timers all done in the main thread - have a list of timers that you keep appending new ones to. Each timer doesn't actually do anything, it just has a time when it goes off - which is easier if you work in arbitrary 'rounds' than in real time, but still doable. Each interval, the mainloop should check all of them, and see if it is time (or past time) for them to expire - if it is, remove them from the list (of course, be careful about removing items from a list you're iterating over - it mightn't do what you expect).

If you have a lot of timers, and by profiling you find out that running through all of them every interval is costing you too much time, a simple optimisation would be to keep them in a heapq - this will keep them sorted for you, so you know after the first one that hasn't expired yet that none of the rest have either. Something like:

while True:
    if not q:
       break
    timer = heapq.heappop(q)
    if timer.expiry <= currenttime:
       # trigger events
    else:
       heapq.heappush(q)
       break

This does still cost you one unnecessary pop/push pair, but its hard to see how you would do better - again, doing something like:

for timer in q:
    if timer.expiry <= currenttime:
       heapq.heappop(timer)
       # trigger events
    else:
       break

Can have subtle bugs because list iterators (functions in heapq work on sequences and use side effects, rather than there being a full-fledged heapq class for some reason) work by keeping track of what index they're up to - so if you remove the current element, you push everything after it one index to the left and end up skipping the next one.

The only important thing is that currenttime is consistently updated each interval in the main loop (or, if your heart is set on having it in real time, based on the system clock), and timer.expiry is measured in the same units - if you have a concept of 'rounds', and a trap lasts six rounds, when it is placed you would do heapq.heappush(q, Timer(expiry=currenttime+6).

If you do want to do it the multithreaded way, your way of having a producer/consumer queue for cleanup will work - you just need to not use Queue.join(). Instead, as the timer in a thread runs out, it calls q.put(), and then dies. The mainloop would use q.get(False), which will avoid blocking, or else q.get(True, 0.1) which will block for at most 0.1 seconds - the timeout can be any positive number; tune it carefully for the best tradeoff between blocking long enough that clients notice and having events go off late because they only just missed being in the queue on time.

于 2012-06-18T09:44:15.870 回答
0

主线程创建一个队列和一堆从队列中拉出任务的工作线程。只要队列为空,所有工作线程都会阻塞并且什么也不做。当一个任务被放入队列时,一个随机的工作线程获取该任务,完成它的工作并在它准备好后立即休眠。这样,您可以一遍又一遍地重用线程,而无需创建新的工作线程。

当您需要停止线程时,您将一个 kill 对象放入队列中,该对象告诉线程关闭而不是阻塞队列。

于 2012-06-18T09:53:28.800 回答