如何让3个线程按顺序打印
How make 3 threads print in sequence
我需要制作 3 个线程来打印信号灯的颜色:红色、黄色和绿色,然后,每个线程必须随机休眠 N 秒。
每种颜色必须用一根线印,整个过程要重复N次。
我试过将 lock.acquire() 和 lock.release() 移出 for 循环但不起作用 =(
from termcolor import colored
import threading
import time
from random import randrange
def threadRed(n, lock, tempo):
for i in range(n):
lock.acquire()
print(colored("red", 'grey', 'on_red', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'red'))
time.sleep(tempo)
lock.release()
def threadYellow(n, lock, tempo):
for i in range(n):
lock.acquire()
print(colored("yellow", 'grey', 'on_yellow', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'yellow'))
time.sleep(tempo)
lock.release()
def threadGreen(n, lock, tempo):
for i in range(n):
lock.acquire()
print(colored("green", 'grey', 'on_green', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'green'))
time.sleep(tempo)
lock.release()
lock = threading.Lock()
repeticoes = 5
tempo = randrange(1, 11)
t_red = threading.Thread(target=threadRed, args=(repeticoes, lock, tempo))
tempo = randrange(1, 11)
t_yellow = threading.Thread(target=threadYellow, args=(repeticoes, lock, tempo))
tempo = randrange(1, 11)
t_green = threading.Thread(target=threadGreen, args=(repeticoes, lock, tempo))
t_red.start()
t_yellow.start()
t_green.start()
t_red.join()
t_yellow.join()
t_green.join()
简而言之,我的代码正在打印:
但我需要这个作为显示结果:
好的,你想要的输出会扼杀 multi-threading
的全部意义。
为什么?
A thread has a beginning, an execution sequence, and a conclusion. It
has an instruction pointer that keeps track of where within its
context it is currently running.
从那里继续,你的问题的重点是 运行 同时处理多个线程,而不考虑 function
首先执行的事实。
您正在尝试的是:
运行 线程是按顺序排列的,不管哪个线程先完成,那不是multi-threading
。除此之外,您在每个函数中使用 lock.acquire() and lock.release()
来 摆脱多线程
答案:
如果您真的希望线程以顺序方式运行,则不应在函数内获取和释放线程,
一点变化:
from termcolor import colored
import threading
import time
from random import randrange
def threadRed(n, tempo):
for i in range(n):
# lock.acquire()
print(colored("red", 'grey', 'on_red', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'red'))
time.sleep(tempo)
# lock.release()
def threadYellow(n, tempo):
for i in range(n):
# lock.acquire()
print(colored("yellow", 'grey', 'on_yellow', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'yellow'))
time.sleep(tempo)
# lock.release()
def threadGreen(n, tempo):
for i in range(n):
# lock.acquire()
print(colored("green", 'grey', 'on_green', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'green'))
time.sleep(tempo)
# lock.release()
lock = threading.Lock()
repeticoes = 5
lock.acquire()
tempo = randrange(1, 11)
t_red = threading.Thread(target=threadRed, args=(repeticoes, tempo))
tempo = randrange(1, 11)
t_yellow = threading.Thread(target=threadYellow, args=(repeticoes, tempo))
tempo = randrange(1, 11)
t_green = threading.Thread(target=threadGreen, args=(repeticoes, tempo))
lock.release()
t_red.start()
t_yellow.start()
t_green.start()
t_red.join()
t_yellow.join()
t_green.join()
输出:
red
I'm going to sleep for 6 seconds,
yellow
I'm going to sleep for 4 seconds,
green
I'm going to sleep for 4 seconds,
yellow
I'm going to sleep for 4 seconds,
green
I'm going to sleep for 4 seconds,
red
I'm going to sleep for 6 seconds,
yellow
I'm going to sleep for 4 seconds,
green
I'm going to sleep for 4 seconds,
red
I'm going to sleep for 6 seconds,
不要尝试使用 threading.Lock()
。 lock
对象仅用于互斥(即防止两个或多个线程同时访问同一数据。)它不用于 [=] 之间的通信37=] 个线程。
IMO,最好的方法是使用三个 Semaphore
实例。 Python有一个class、asyncio.Semaphore
,但我对其文档中的"not thread safe"这几个字有点疑惑。我从未使用过 class,但它 看起来 像其他语言库中的信号量,用于在线程之间发送信号。
信号量就像一个包含零个或多个许可的阻塞队列。许可证是抽象的;它们实际上并不存在。信号量只是记录在任何给定时刻它应该 "contain" 的数量。
调用者可以尝试 acquire()
一个许可,这将减少计数并立即 return 如果计数大于零,或者它将等到其他线程 release()
否则是许可证。
下面是您将如何使用它:
创建三个空信号量 (count == 0),每个线程一个,并为每个线程提供对其自身信号量和下一个线程信号量的引用。然后每个线程应该循环:
for i in range(n):
self.my_semaphore.acquire() # thread waits here until signalled.
print( ... )
self.next_guys_semaphore.release() # signals the next guy.
在您的主线程创建了三个信号量和三个工作线程之后,将不会发生任何事情,因为所有三个工作线程都将在 acquire()
中等待。那么,主线程需要做的最后一件事是red_worker_semaphore.release()
,然后它们应该开始运行,一个接一个,以正确的顺序。
我成功了!
感谢大家的提示!但是我使用 threading.Lock() 和 threading.Event() 重新编写了我所有的代码并且工作正常!
from termcolor import colored
import threading
import time
from random import randrange
lock = threading.Lock()
event = threading.Event()
def printThread(color):
duration = randrange(1, 11)
print(colored(color, 'grey', 'on_'+color, attrs=['dark', 'bold']))
print(colored("I'm going sleep for %d seconds!," % duration, color))
time.sleep(duration)
def threadRed(n):
for i in range(n):
lock.acquire()
printThread("red")
lock.release()
event.set()
event.wait()
event.clear()
def threadYellow(n):
for i in range(n):
lock.acquire()
printThread("yellow")
lock.release()
event.set()
event.wait()
event.clear()
def threadGreen(n):
for i in range(n):
lock.acquire()
printThread("green")
lock.release()
event.set()
event.wait()
event.clear()
loop_count = 5
t_red = threading.Thread(target=threadRed, args=(loop_count,))
t_yellow = threading.Thread(target=threadYellow, args=(loop_count,))
t_green = threading.Thread(target=threadGreen, args=(loop_count,))
t_red.start()
t_yellow.start()
t_green.start()
t_red.join()
t_yellow.join()
t_green.join()
那是相同代码的另一个版本,但使用纯信号量,而不是事件
from termcolor import colored
import threading
import time
from random import randrange
semaforo1 = threading.Semaphore()
semaforo2 = threading.Semaphore()
semaforo3 = threading.Semaphore()
def printThread(color):
duration = randrange(1, 11)
print(colored(color, 'grey', 'on_'+color, attrs=['dark', 'bold']))
print(colored("I'm going sleep for %d seconds!," % duration, color))
time.sleep(duration)
def threadRed(n):
semaforo2.acquire()
semaforo3.acquire()
for i in range(n):
semaforo1.acquire()
printThread("red")
#semaforo1.release()
semaforo2.release()
def threadYellow(n):
for i in range(n):
semaforo2.acquire()
printThread("yellow")
semaforo3.release()
def threadGreen(n):
for i in range(n):
semaforo3.acquire()
printThread("green")
semaforo1.release()
loop_count = 5
t_red = threading.Thread(target=threadRed, args=(loop_count,))
t_yellow = threading.Thread(target=threadYellow, args=(loop_count,))
t_green = threading.Thread(target=threadGreen, args=(loop_count,))
t_red.start()
t_yellow.start()
t_green.start()
t_red.join()
t_yellow.join()
t_green.join()
我需要制作 3 个线程来打印信号灯的颜色:红色、黄色和绿色,然后,每个线程必须随机休眠 N 秒。 每种颜色必须用一根线印,整个过程要重复N次。
我试过将 lock.acquire() 和 lock.release() 移出 for 循环但不起作用 =(
from termcolor import colored
import threading
import time
from random import randrange
def threadRed(n, lock, tempo):
for i in range(n):
lock.acquire()
print(colored("red", 'grey', 'on_red', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'red'))
time.sleep(tempo)
lock.release()
def threadYellow(n, lock, tempo):
for i in range(n):
lock.acquire()
print(colored("yellow", 'grey', 'on_yellow', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'yellow'))
time.sleep(tempo)
lock.release()
def threadGreen(n, lock, tempo):
for i in range(n):
lock.acquire()
print(colored("green", 'grey', 'on_green', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'green'))
time.sleep(tempo)
lock.release()
lock = threading.Lock()
repeticoes = 5
tempo = randrange(1, 11)
t_red = threading.Thread(target=threadRed, args=(repeticoes, lock, tempo))
tempo = randrange(1, 11)
t_yellow = threading.Thread(target=threadYellow, args=(repeticoes, lock, tempo))
tempo = randrange(1, 11)
t_green = threading.Thread(target=threadGreen, args=(repeticoes, lock, tempo))
t_red.start()
t_yellow.start()
t_green.start()
t_red.join()
t_yellow.join()
t_green.join()
简而言之,我的代码正在打印:
但我需要这个作为显示结果:
好的,你想要的输出会扼杀 multi-threading
的全部意义。
为什么?
A thread has a beginning, an execution sequence, and a conclusion. It has an instruction pointer that keeps track of where within its context it is currently running.
从那里继续,你的问题的重点是 运行 同时处理多个线程,而不考虑 function
首先执行的事实。
您正在尝试的是:
运行 线程是按顺序排列的,不管哪个线程先完成,那不是multi-threading
。除此之外,您在每个函数中使用 lock.acquire() and lock.release()
来 摆脱多线程
答案: 如果您真的希望线程以顺序方式运行,则不应在函数内获取和释放线程,
一点变化:
from termcolor import colored
import threading
import time
from random import randrange
def threadRed(n, tempo):
for i in range(n):
# lock.acquire()
print(colored("red", 'grey', 'on_red', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'red'))
time.sleep(tempo)
# lock.release()
def threadYellow(n, tempo):
for i in range(n):
# lock.acquire()
print(colored("yellow", 'grey', 'on_yellow', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'yellow'))
time.sleep(tempo)
# lock.release()
def threadGreen(n, tempo):
for i in range(n):
# lock.acquire()
print(colored("green", 'grey', 'on_green', attrs=['dark', 'bold']))
print(colored("I'm going to sleep for %d seconds," % tempo, 'green'))
time.sleep(tempo)
# lock.release()
lock = threading.Lock()
repeticoes = 5
lock.acquire()
tempo = randrange(1, 11)
t_red = threading.Thread(target=threadRed, args=(repeticoes, tempo))
tempo = randrange(1, 11)
t_yellow = threading.Thread(target=threadYellow, args=(repeticoes, tempo))
tempo = randrange(1, 11)
t_green = threading.Thread(target=threadGreen, args=(repeticoes, tempo))
lock.release()
t_red.start()
t_yellow.start()
t_green.start()
t_red.join()
t_yellow.join()
t_green.join()
输出:
red
I'm going to sleep for 6 seconds,
yellow
I'm going to sleep for 4 seconds,
green
I'm going to sleep for 4 seconds,
yellow
I'm going to sleep for 4 seconds,
green
I'm going to sleep for 4 seconds,
red
I'm going to sleep for 6 seconds,
yellow
I'm going to sleep for 4 seconds,
green
I'm going to sleep for 4 seconds,
red
I'm going to sleep for 6 seconds,
不要尝试使用 threading.Lock()
。 lock
对象仅用于互斥(即防止两个或多个线程同时访问同一数据。)它不用于 [=] 之间的通信37=] 个线程。
IMO,最好的方法是使用三个 Semaphore
实例。 Python有一个class、asyncio.Semaphore
,但我对其文档中的"not thread safe"这几个字有点疑惑。我从未使用过 class,但它 看起来 像其他语言库中的信号量,用于在线程之间发送信号。
信号量就像一个包含零个或多个许可的阻塞队列。许可证是抽象的;它们实际上并不存在。信号量只是记录在任何给定时刻它应该 "contain" 的数量。
调用者可以尝试 acquire()
一个许可,这将减少计数并立即 return 如果计数大于零,或者它将等到其他线程 release()
否则是许可证。
下面是您将如何使用它:
创建三个空信号量 (count == 0),每个线程一个,并为每个线程提供对其自身信号量和下一个线程信号量的引用。然后每个线程应该循环:
for i in range(n):
self.my_semaphore.acquire() # thread waits here until signalled.
print( ... )
self.next_guys_semaphore.release() # signals the next guy.
在您的主线程创建了三个信号量和三个工作线程之后,将不会发生任何事情,因为所有三个工作线程都将在 acquire()
中等待。那么,主线程需要做的最后一件事是red_worker_semaphore.release()
,然后它们应该开始运行,一个接一个,以正确的顺序。
我成功了!
感谢大家的提示!但是我使用 threading.Lock() 和 threading.Event() 重新编写了我所有的代码并且工作正常!
from termcolor import colored
import threading
import time
from random import randrange
lock = threading.Lock()
event = threading.Event()
def printThread(color):
duration = randrange(1, 11)
print(colored(color, 'grey', 'on_'+color, attrs=['dark', 'bold']))
print(colored("I'm going sleep for %d seconds!," % duration, color))
time.sleep(duration)
def threadRed(n):
for i in range(n):
lock.acquire()
printThread("red")
lock.release()
event.set()
event.wait()
event.clear()
def threadYellow(n):
for i in range(n):
lock.acquire()
printThread("yellow")
lock.release()
event.set()
event.wait()
event.clear()
def threadGreen(n):
for i in range(n):
lock.acquire()
printThread("green")
lock.release()
event.set()
event.wait()
event.clear()
loop_count = 5
t_red = threading.Thread(target=threadRed, args=(loop_count,))
t_yellow = threading.Thread(target=threadYellow, args=(loop_count,))
t_green = threading.Thread(target=threadGreen, args=(loop_count,))
t_red.start()
t_yellow.start()
t_green.start()
t_red.join()
t_yellow.join()
t_green.join()
那是相同代码的另一个版本,但使用纯信号量,而不是事件
from termcolor import colored
import threading
import time
from random import randrange
semaforo1 = threading.Semaphore()
semaforo2 = threading.Semaphore()
semaforo3 = threading.Semaphore()
def printThread(color):
duration = randrange(1, 11)
print(colored(color, 'grey', 'on_'+color, attrs=['dark', 'bold']))
print(colored("I'm going sleep for %d seconds!," % duration, color))
time.sleep(duration)
def threadRed(n):
semaforo2.acquire()
semaforo3.acquire()
for i in range(n):
semaforo1.acquire()
printThread("red")
#semaforo1.release()
semaforo2.release()
def threadYellow(n):
for i in range(n):
semaforo2.acquire()
printThread("yellow")
semaforo3.release()
def threadGreen(n):
for i in range(n):
semaforo3.acquire()
printThread("green")
semaforo1.release()
loop_count = 5
t_red = threading.Thread(target=threadRed, args=(loop_count,))
t_yellow = threading.Thread(target=threadYellow, args=(loop_count,))
t_green = threading.Thread(target=threadGreen, args=(loop_count,))
t_red.start()
t_yellow.start()
t_green.start()
t_red.join()
t_yellow.join()
t_green.join()