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

时间:2018-11-08 19:46:05

标签: python-3.x multithreading sleep

我正在尝试在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,现在我想继续尝试下去,希望它能很好地结束:) 哦,此外,输出是否重叠也没关系。

1 个答案:

答案 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的东西,基本上(有一些例外)一次只能运行一个线程,而其他线程则处于休眠状态。


Threading documentation

Queue documentation