我正在尝试在python3中创建一个简单的thread
,其中test1
将运行到一定数量,然后sleep
,而test2
仍将运行,当达到一定数量时也会进入睡眠状态。
我的代码是这样的:
def test2(count):
if count == 8:
print("sleep for 4 sec")
time.sleep(3.0)
print("test2 thread = {}".format(count))
def test1(count):
if count == 5:
print("sleep for 5 sec")
time.sleep(3.0)
print("test1 thread = {}".format(count))
for num in range(0,10):
t1 = threading.Thread(target=test1, args=(num,))
t2 = threading.Thread(target=test2, args=(num,))
t1.start()
t2.start()
此外,我之前一直在使用python进行编码,但没有使用thread
,现在我想继续尝试下去,希望它能很好地结束:)
哦,此外,输出是否重叠也没关系。
答案 0 :(得分:1)
threading.Thread()
创建新线程,而t1.start()
只是将其分派。
此代码:
for num in range(0,10):
t1 = threading.Thread(target=test1, args=(num,))
t2 = threading.Thread(target=test2, args=(num,))
t1.start()
t2.start()
实际上每次迭代创建并启动2个新线程。最后,您有20个线程+主线程。
另外,当您启动线程时,您应该等到线程结束或将其作为守护程序线程运行。使用守护程序线程,您是在说我不在乎您做什么以及何时结束。
基本线程用法如下所示:
import threading
def do_stuff():
print("Stuff on thread {}".format(threading.get_ident()))
print("Main thread {}".format(threading.get_ident()))
t = threading.Thread(target=do_stuff) # Specify what should be running in new thread
t.start() # Dispatch thread
t.join() # Wait until the thread is done
注意:threading.get_ident()
为您提供了调用此函数的线程的唯一标识符。
现在从您的示例中,如果要启动2个独立线程,可以执行以下操作:
import threading
import time
def test2():
for count in range(0, 10):
if count == 8:
print("test2: sleep for 4 sec")
time.sleep(3.0)
print("test2: thread = {}".format(count))
def test1():
for count in range(0, 10):
if count == 5:
print("test 1: sleep for 5 sec")
time.sleep(3.0)
print("test1: thread = {}".format(count))
t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
t1.start()
t2.start()
t1.join()
t2.join()
但是您可能想要同步这些线程并在“相同”时间向它们发送一些项目。
import threading
# Create threads
t1 = threading.Thread(target=test1)
t2 = threading.Thread(target=test2)
# Run threads
t1.start()
t2.start()
# Go through some list or whatever
for num in range(0,10):
# send num to t1
# send num to t2
# wait for t1 and t2
pass
# Wait until threads are finished with their jobs
t1.join()
t2.join()
要向其他线程发送值,我们可以使用queue.Queue。您可以安全地将值放在一个线程中,而第二个线程可以读取它,或者等到有东西(或多个线程可以写入并且多个线程可以读取)。
import threading
import time
import queue
def test2(q):
while True:
count = q.get() # Get data from the q2 queue
if count == 8:
print("test2: sleep for 4 sec")
time.sleep(3.0)
print("test2: thread = {}".format(count))
def test1(q):
while True:
count = q.get() # Get data from the q1 queue
if count == 5:
print("test 1: sleep for 5 sec")
time.sleep(3.0)
print("test1: thread = {}".format(count))
# Creates queues
q1 = queue.Queue()
q2 = queue.Queue()
# Create threads
t1 = threading.Thread(target=test1, args=(q1, ))
t2 = threading.Thread(target=test2, args=(q2, ))
# Run threads
t1.start()
t2.start()
# Go through some list or whatever
for num in range(0, 10):
# send num to t1
q1.put(num)
# send num to t2
q2.put(num)
# wait for t1 and t2
# ???
# Wait until threads are finished with their jobs
t1.join()
t2.join()
哦,等等...我们如何知道线程已完成其工作,并且我们可以发送另一个值?好了,我们可以再次使用Queue
。创建新对并发送例如True
函数结尾处的test?
,然后等待从这些队列的主循环中读取。但是,要发送状态信息,我们应该使用threading.Event
。
import threading
import time
import queue
def test2(q, e):
while True:
count = q.get() # Get data from the q2 queue
if count == 8:
print("test2: sleep for 4 sec")
time.sleep(3.0)
print("test2: thread = {}".format(count))
e.set() # Inform master the processing of given value is done
def test1(q, e):
while True:
count = q.get() # Get data from the q1 queue
if count == 5:
print("test 1: sleep for 5 sec")
time.sleep(3.0)
print("test1: thread = {}".format(count))
e.set() # Inform master the processing of given value is done
# Creates queues
q1 = queue.Queue()
q2 = queue.Queue()
# Create events
e1 = threading.Event()
e2 = threading.Event()
# Create threads
t1 = threading.Thread(target=test1, args=(q1, e1))
t2 = threading.Thread(target=test2, args=(q2, e2))
# Run threads
t1.start()
t2.start()
# Go through some list or whatever
for num in range(0, 10):
# send num to t1
q1.put(num)
# send num to t2
q2.put(num)
# wait for t1
e1.wait()
# wait for t2
e2.wait()
# Wait until threads are finished with their jobs
t1.join()
t2.join()
现在我们快到了,但是脚本永远不会结束。这是因为test?
函数(线程)在无限循环中等待数据(来自队列q1 / q2)。我们需要某种方式来告诉他们“好吧,这就是所有人”。为此,我们可以说队列中的None值表示结束。结果如下:
import threading
import time
import queue
def test2(q, e):
while True:
count = q.get() # Get data from the q2 queue
if count is None: # Exit on None value
return
if count == 8:
print("test2: sleep for 4 sec")
time.sleep(3.0)
print("test2: thread = {}".format(count))
e.set() # Inform master the processing of given value is done
def test1(q, e):
while True:
count = q.get() # Get data from the q1 queue
if count is None: # Exit on None value
return
if count == 5:
print("test 1: sleep for 5 sec")
time.sleep(3.0)
print("test1: thread = {}".format(count))
e.set() # Inform master the processing of given value is done
# Creates queues
q1 = queue.Queue()
q2 = queue.Queue()
# Create events
e1 = threading.Event()
e2 = threading.Event()
# Create threads
t1 = threading.Thread(target=test1, args=(q1, e1))
t2 = threading.Thread(target=test2, args=(q2, e2))
# Run threads
t1.start()
t2.start()
# Go through some list or whatever
for num in range(0, 10):
# send num to t1
q1.put(num)
# send num to t2
q2.put(num)
# wait for t1
e1.wait()
# wait for t2
e2.wait()
# Inform threads to exit
q1.put(None)
q2.put(None)
# Wait until threads are finished with their jobs
t1.join()
t2.join()
注意:可以在全局线程中共享全局变量或类属性,而不是在线程“ main”函数中使用参数,而是可以使用全局变量。但是通常这是一个坏习惯。
注意线程带来的陷阱,例如异常处理不是那么容易。假设函数test1
在调用e.set()
之前引发异常。然后,主线程永无休止地等待e1.wait()
。
CPython(Python的最常见实现)也有一个名为GIL的东西,基本上(有一些例外)一次只能运行一个线程,而其他线程则处于休眠状态。