在线程 python3 中使用 time.sleep()

using time.sleep() in Thread python3

我正在尝试在 python3 中创建一个简单的 thread,其中 test1 将 运行 直到一定数量,然后 sleeptest2 仍然是 运行ning 并且当它达到一定数量时它会进入睡眠状态。 我的代码是这样的:

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,现在我想尝试一下,希望一切顺利 :) 哦,另外,如果它们重叠,输出也无关紧要。

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()

但您可能希望同步这些线程并在 "same" 时间向它们发送一些项目。

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。创建新对并发送,例如Truetest? 函数的末尾,然后等待在主循环中从这些队列中读取。但是为了发送状态信息,我们应该使用 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)。我们需要一些方法来告诉他们 "Ok, that's all folks"。为此,我们可以说队列中的 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" 函数中使用参数,因为全局变量或 class 属性在所有线程之间共享。但通常这是不好的做法。


注意线程带来的陷阱,例如异常处理不是那么容易。假设函数 test1 在调用 e.set() 之前引发异常。然后主线程永远不会结束等待 e1.wait().

此外,CPython(Python 的最常见实现)有一个叫做 GIL 的东西,基本上(有一些例外)只允许 运行ning 1一个线程,其他人正在睡觉。


Threading documentation

Queue documentation