我在应用程序中使用4个线程,它返回我想要打印给用户的文本。 由于我想避免线程独立地打印这些文本,我创建了一个类来管理它......
我不知道我在这里做错了什么,但它仍然没有用。
您可以在下面看到的代码:
from threading import Thread
import time
import random
class Creature:
def __init__(self, name, melee, shielding, health, mana):
self.name = name
self.melee = melee
self.shielding = shielding
self.health = health
self.mana = mana
def attack(self, attacker, opponent, echo):
while 0 != 1:
time.sleep(1)
power = random.randint(1, attacker.melee)
resistance = random.randint(1, opponent.shielding)
resultant = power - resistance
if resistance > 0:
opponent.health -= resistance
if opponent.health < 0:
msg = opponent.name, " is dead"
echo.message(msg)
quit()
else:
msg = opponent.name, " lost ", resistance, " hit points due to an attack by ", attacker.name
echo.message(msg)
def healing(self, healed, echo):
while 0 != 1:
time.sleep(1)
if self.mana >= 25:
if healed.health >= 0:
if healed.health < 50:
life = random.randint(1, 50)
self.mana -= 25
healed.health += life
if healed.health > 100:
healed.health = 100
msg = healed.name, " has generated himself and now has ", self.health, " hit points"
echo.message(msg)
else:
quit()
class echo:
def message(self, msg):
print msg
myEcho = echo()
Monster = Creature("Wasp", 30, 15, 100, 100)
Player = Creature("Knight", 25, 20, 100, 100)
t1 = Thread(target = Player.attack, args = (Monster, Player, myEcho))
t1.start()
t2 = Thread(target = Monster.attack, args = (Player, Monster, myEcho))
t2.start()
t3 = Thread(target=Player.healing(Player, myEcho), args=())
t3.start()
t4 = Thread(target=Monster.healing(Monster, myEcho), args=())
t4.start()
在这里你可以看到混乱的输出:
*('Wasp'('Knight', ' l, ' lost ', ost 13, ' hit points ', 4, due to an attack by '' hi, 'Waspt poi')nts d
ue to an attack by ', 'Knight')
('Wasp', ' lost ', 12, ' hit points due to an attack by ', 'Knight')
('Knight', ' lost ', 17, ' hit points due to an attack by ', 'Wasp')
('Wasp', ' lost ', 6, ' hit points due to an attack by ', 'Knight'('Knight')
, ' lost ', 1, ' hit points due to an attack by ', 'Wasp')
('Wasp', ' lost ', 5, ' hit points due to an attack by ', 'Knight')
('Knight', ' lost ', 13, ' hit points due to an attack by ', 'Wasp')
(('Wa'Knighsp't', , ' los' lostt ' ', , 32, ' hit points due to an attack by ', 'Knight')
, ' hit points due to an attack by ', 'Wasp')*
你们有任何想法如何解决这个问题吗?
谢谢!
答案 0 :(得分:4)
使用信号量。一个例子是:
from threading import *
screen_lock = Semaphore(value=1)
现在,每当你的过程想要写一些东西时,它就会:
screen_lock.acquire()
print("Something!")
screen_lock.release()
答案 1 :(得分:3)
使用threading.Semaphore
确保不会发生任何冲突:
screenlock = Semaphore(value=1) # You'll need to add this to the import statement.
然后,在致电echo.message
之前,请插入此行以获取输出权:
screenlock.acquire()
然后在之后调用echo.message
这一行以便允许打印另一个帖子:
screenlock.release()
答案 2 :(得分:3)
比信号量稍微好一点是重入锁定。
from threading import RLock
class SynchronizedEcho(object):
print_lock = RLock()
def __init__(self, global_lock=True):
if not global_lock:
self.print_lock = RLock()
def __call__(self, msg):
with self.print_lock:
print(msg)
echo = SynchronizedEcho()
echo("Test")
可重入锁的好处是它可以与with
语句一起使用。也就是说,如果在使用锁定时抛出任何异常,您可以确保它将在with块结束时释放。要使用信号量执行相同操作,您必须记住编写try-finally块。
值得注意的是,在访问和修改Creatures的属性时,您还应该使用信号量或锁定。这是因为您有多个线程来修改属性的值。所以同样的方式是一个打印被另一个打印中断,输出乱码,所以你的属性会变得乱码。
请考虑以下事项:
主题A
# health starts as 110
if healed.health > 100:
# Thread A is interrupted and Thread B starts executing
# health is now 90
healed.health = 100
# health is now set to 100 -- ignoring the 20 damage that was done
主题B
# health is 110 and resistance is 20
opponent.health -= resistance
# health is now 90.
# Thread B is interrupted and Thread A starts executing
答案 3 :(得分:0)
使用“日志记录”模块代替打印。 日志记录是线程安全的,因此每个线程将按预期完成写入操作
在这里您可以找到有关如何使用日志记录的说明 about logging from python module of the week
在这里您可以看到它是线程安全的 from python doc