重用Python中的一个线程

时间:2017-05-25 00:11:42

标签: python multithreading

我试图为文字游戏编写实时战斗系统。我希望玩家能够采取行动并且必须等待一定时间才能再次行动,而NPC也在这样做。

我写了一个小例子:

import threading
import time

def playerattack():
    print("You attack!")
    time.sleep(2)


def npcattack():
    while hostile == True:
        print("The enemy attacks!")
        time.sleep(3)

p = threading.Thread(target=playerattack)
n = threading.Thread(target=npcattack)

hostile = False

while True:
    if hostile == True:
        n.start()
    com = input("enter 'attack' to attack:")
    if 'attack' in com:
        hostile = True
        p.start()

该示例适用于第一次攻击: 我进入攻击',敌对标志设置为True,npc攻击线程启动,但我得到一个' RuntimeError:线程只能启动一次'当我再次尝试攻击时。

有没有办法重用该线程而不会抛出错误?或者我是不是错了?

3 个答案:

答案 0 :(得分:0)

问题是该线程已经在运行,并且由于while循环再次调用n.start(),您无法再次启动正在运行的线程。

即使线程已经死亡,您仍需要重新初始化线程实例并重新开始。您无法启动旧实例。

while True循环的情况下,它试图多次启动一个线程。你做的是检查线程是否正在运行,如果没有运行则启动线程实例。

import threading
import time

def playerattack():
    print("You attack!")
    time.sleep(2)


def npcattack():
    while hostile:
        print("The enemy attacks!")
        time.sleep(3)

p = threading.Thread(target=playerattack)
n = threading.Thread(target=npcattack)

hostile = False

while True:
    if hostile and not n.is_alive():
        try:
            n.start()
        except RuntimeError: #occurs if thread is dead
            n = threading.Thread(target=npcattack) #create new instance if thread is dead
            n.start() #start thread

    com = input("enter 'attack' to attack:")

    if 'attack' in com:
        hostile = True
        if not p.is_alive():
            try:
                p.start()
            except RuntimeError: #occurs if thread is dead
                p = threading.Thread(target=playerattack) #create new instance if thread is dead
                p.start()

答案 1 :(得分:0)

我们从start()方法开始线程。 之后,我们使用run()方法,即p.run()n.run()而不是p.start()n.start()来重用同一线程。

答案 2 :(得分:0)

如果您只是想更改线程“链接”到的函数的参数,我通过创建子类并实现了reset方法,发现了一种重用threading.Thread对象的(巧妙的)方法。 / p>

class ReusableThread(threading.Thread):
    def __init__(self, *args, **kwargs):
        threading.Thread.__init__(self,*args, **kwargs)
        self._default_args = self._target, self._args, self._kwargs

    def run(self, *args, **kwargs):
        super().run()
        self.reset()
        
    def reset(self, *args, **kwargs):
        self._target = self._default_args[0]
        self._args = args or self._default_args[1]
        self._kwargs = kwargs or self._default_args[2]

在python shell中:

>>> r  = ReusableThread(target=print, args=("banana",))
>>> r.start()
banana
>>> r.reset(("banana", "apple"), "kiwi", sep='\n', end="<<<\n")
>>> r.run()
('banana', 'apple')
kiwi<<<
>>>