Python 队列未按顺序拉取线程对象。只处理永不结束的最后一个线程
Python Queue not pulling thread objects in order. Only working on last thread which never ends
当 运行 我的代码时,“出纳员”线程一遍又一遍地帮助同一个“客户”线程,直到不确定的次数。我不明白为什么最后创建的客户在创建其他线程时得到了一次又一次的帮助。
我不确定在客户线程的代码中某处是否需要 .join()。我把它放在代码中的多个地方,我的代码似乎卡住了。
from threading import Semaphore, Thread, Lock
from queue import Queue, Empty
from random import randint
from time import sleep
max_customers_in_bank = 10
'''maximum number of customers that can be in
the bank at one time'''
max_customers = 7 # number of customers that will go to the bank today
max_tellers = 2 # number of tellers working today
teller_timeout = 10 # longest time that a teller will wait for new customers
# Part I
class Customer:
def __init__(self, name):
self.name = name
def __str__(self):
return {self.name}
class Teller:
def __init__(self, name):
self.name = name
def __str__(self):
return {self.name}
def bankprint(lock, msg):
# Print message with a context manager lock
with lock:
print(msg)
def wait_outside_bank(customer, guard, teller_line, printlock):
# Call bankprint and format customer object string approiately for call
bankprint(printlock, ("(C) '" + customer.name + "' waiting outside bank"))
# Create semphore for max customers and aquire it
guard.acquire()
bankprint(printlock,
("<G> Security guard letting '" +
customer.name + "' into the bank"))
bankprint(printlock, ("(C) '" + customer.name + "' getting into line"))
# Create teller line queue and put custiomers into queue
teller_line.put(customer)
# Part III
def teller_job(teller, guard, teller_line, printlock):
bankprint(printlock, ("[T] '" + teller.name + "' starting work"))
while True:
try:
teller_line.get(timeout=teller_timeout)
bankprint(printlock, ("[T] '" + teller.name + "' is now helping" +
customer.name))
sleep(randint(1, 4))
bankprint(printlock, ("[T] '" + teller.name + "' is done helping" +
customer.name))
bankprint(printlock, ("<G> Security guard letting '" +
customer.name + "' out of the bank"))
guard.release()
except Empty:
bankprint(printlock, ("[T] Nobody is in line, '" + teller.name +
"' is going on break"))
break
if __name__ == "__main__":
printlock = Lock()
teller_line = Queue(maxsize=max_customers_in_bank)
guard = Semaphore(max_customers_in_bank)
Customer_List = [Customer("Customer_"+str(i)) for i in
range(1, max_customers+1)]
for customer in Customer_List:
thread = Thread(target=wait_outside_bank,
args=(customer, guard, teller_line, printlock))
thread.start()
sleep(5)
print("*B* Tellers starting work")
Teller_List = [Teller("Teller_"+str(i)) for i in range(1, max_tellers+1)]
Teller_Threads = [Thread(target = teller_job, args = (teller, guard, teller_line, printlock)) for teller in Teller_List]
for teller in Teller_Threads:
teller.start()
for teller in Teller_Threads:
teller.join()
print("*B* Bank closed")
示例输出:
(C) 'Customer_1' waiting outside bank
<G> Security guard letting 'Customer_1' into the bank
(C) 'Customer_1' getting into line
(C) 'Customer_2' waiting outside bank
(C) 'Customer_3' waiting outside bank
<G> Security guard letting 'Customer_2' into the bank
(C) 'Customer_4' waiting outside bank
<G> Security guard letting 'Customer_3' into the bank
(C) 'Customer_3' getting into line
(C) 'Customer_2' getting into line
(C) 'Customer_6' waiting outside bank
<G> Security guard letting 'Customer_4' into the bank
(C) 'Customer_4' getting into line
(C) 'Customer_7' waiting outside bank
<G> Security guard letting 'Customer_6' into the bank
(C) 'Customer_5' waiting outside bank
<G> Security guard letting 'Customer_7' into the bank
(C) 'Customer_7' getting into line
<G> Security guard letting 'Customer_5' into the bank
(C) 'Customer_5' getting into line
(C) 'Customer_6' getting into line
*B* Tellers starting work
[T] 'Teller_1' starting work
[T] 'Teller_1' is now helpingCustomer_7
[T] 'Teller_2' starting work
[T] 'Teller_2' is now helpingCustomer_7
[T] 'Teller_1' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_1' is now helpingCustomer_7
[T] 'Teller_2' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_2' is now helpingCustomer_7
[T] 'Teller_1' is done helpingCustomer_7
[T] 'Teller_2' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_1' is now helpingCustomer_7
[T] 'Teller_2' is now helpingCustomer_7
[T] 'Teller_1' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_1' is now helpingCustomer_7
[T] 'Teller_2' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_1' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] Nobody is in line, 'Teller_2' is going on break
[T] Nobody is in line, 'Teller_1' is going on break
*B* Bank closed
teller_job
没有定义 customer
,因此当您使用 customer.name
时,您使用的是全局命名空间中的 customer
。它是在 for 循环 for customer in Customer_List:
中分配的,并且在线程进行处理之前该循环已完成(将列表中的最后一个客户保留为最后一个值)。
当 运行 我的代码时,“出纳员”线程一遍又一遍地帮助同一个“客户”线程,直到不确定的次数。我不明白为什么最后创建的客户在创建其他线程时得到了一次又一次的帮助。
我不确定在客户线程的代码中某处是否需要 .join()。我把它放在代码中的多个地方,我的代码似乎卡住了。
from threading import Semaphore, Thread, Lock
from queue import Queue, Empty
from random import randint
from time import sleep
max_customers_in_bank = 10
'''maximum number of customers that can be in
the bank at one time'''
max_customers = 7 # number of customers that will go to the bank today
max_tellers = 2 # number of tellers working today
teller_timeout = 10 # longest time that a teller will wait for new customers
# Part I
class Customer:
def __init__(self, name):
self.name = name
def __str__(self):
return {self.name}
class Teller:
def __init__(self, name):
self.name = name
def __str__(self):
return {self.name}
def bankprint(lock, msg):
# Print message with a context manager lock
with lock:
print(msg)
def wait_outside_bank(customer, guard, teller_line, printlock):
# Call bankprint and format customer object string approiately for call
bankprint(printlock, ("(C) '" + customer.name + "' waiting outside bank"))
# Create semphore for max customers and aquire it
guard.acquire()
bankprint(printlock,
("<G> Security guard letting '" +
customer.name + "' into the bank"))
bankprint(printlock, ("(C) '" + customer.name + "' getting into line"))
# Create teller line queue and put custiomers into queue
teller_line.put(customer)
# Part III
def teller_job(teller, guard, teller_line, printlock):
bankprint(printlock, ("[T] '" + teller.name + "' starting work"))
while True:
try:
teller_line.get(timeout=teller_timeout)
bankprint(printlock, ("[T] '" + teller.name + "' is now helping" +
customer.name))
sleep(randint(1, 4))
bankprint(printlock, ("[T] '" + teller.name + "' is done helping" +
customer.name))
bankprint(printlock, ("<G> Security guard letting '" +
customer.name + "' out of the bank"))
guard.release()
except Empty:
bankprint(printlock, ("[T] Nobody is in line, '" + teller.name +
"' is going on break"))
break
if __name__ == "__main__":
printlock = Lock()
teller_line = Queue(maxsize=max_customers_in_bank)
guard = Semaphore(max_customers_in_bank)
Customer_List = [Customer("Customer_"+str(i)) for i in
range(1, max_customers+1)]
for customer in Customer_List:
thread = Thread(target=wait_outside_bank,
args=(customer, guard, teller_line, printlock))
thread.start()
sleep(5)
print("*B* Tellers starting work")
Teller_List = [Teller("Teller_"+str(i)) for i in range(1, max_tellers+1)]
Teller_Threads = [Thread(target = teller_job, args = (teller, guard, teller_line, printlock)) for teller in Teller_List]
for teller in Teller_Threads:
teller.start()
for teller in Teller_Threads:
teller.join()
print("*B* Bank closed")
示例输出:
(C) 'Customer_1' waiting outside bank
<G> Security guard letting 'Customer_1' into the bank
(C) 'Customer_1' getting into line
(C) 'Customer_2' waiting outside bank
(C) 'Customer_3' waiting outside bank
<G> Security guard letting 'Customer_2' into the bank
(C) 'Customer_4' waiting outside bank
<G> Security guard letting 'Customer_3' into the bank
(C) 'Customer_3' getting into line
(C) 'Customer_2' getting into line
(C) 'Customer_6' waiting outside bank
<G> Security guard letting 'Customer_4' into the bank
(C) 'Customer_4' getting into line
(C) 'Customer_7' waiting outside bank
<G> Security guard letting 'Customer_6' into the bank
(C) 'Customer_5' waiting outside bank
<G> Security guard letting 'Customer_7' into the bank
(C) 'Customer_7' getting into line
<G> Security guard letting 'Customer_5' into the bank
(C) 'Customer_5' getting into line
(C) 'Customer_6' getting into line
*B* Tellers starting work
[T] 'Teller_1' starting work
[T] 'Teller_1' is now helpingCustomer_7
[T] 'Teller_2' starting work
[T] 'Teller_2' is now helpingCustomer_7
[T] 'Teller_1' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_1' is now helpingCustomer_7
[T] 'Teller_2' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_2' is now helpingCustomer_7
[T] 'Teller_1' is done helpingCustomer_7
[T] 'Teller_2' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_1' is now helpingCustomer_7
[T] 'Teller_2' is now helpingCustomer_7
[T] 'Teller_1' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_1' is now helpingCustomer_7
[T] 'Teller_2' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] 'Teller_1' is done helpingCustomer_7
<G> Security guard letting 'Customer_7' out of the bank
[T] Nobody is in line, 'Teller_2' is going on break
[T] Nobody is in line, 'Teller_1' is going on break
*B* Bank closed
teller_job
没有定义 customer
,因此当您使用 customer.name
时,您使用的是全局命名空间中的 customer
。它是在 for 循环 for customer in Customer_List:
中分配的,并且在线程进行处理之前该循环已完成(将列表中的最后一个客户保留为最后一个值)。