繁体   English   中英

如何在Python中与线程并行运行两个函数?

[英]How to run two functions in parallel with threading in Python?

我想并行运行两个函数,它们并行打印两个列表。 但是我得到的是一个列表,在另一个列表完成后打印出来。

我尝试了以下代码。

import threading
import time

def fun1():
    testz=['z','y','x','w','v','u','t']
    for j in testz:
        print (j)
        time.sleep(1)

def fun2():
    test=['a','b','c','d','e','f','g']
    for i in test:
        print (i)
        time.sleep(1)


thread1 = threading.Thread(target=fun1())
thread2 = threading.Thread(target=fun2())

thread1.start()
time.sleep(0.5)
thread2.start()

thread1.join()
thread2.join()

我期望的结果是:

z
a
y
b
x
c
w
d
v
e
u
f
t
g

但是我得到的是:

z
y
x
w
v
u
t
a
b
c
d
e
f
g

似乎两个线程正在一个接一个地运行。

问题是您在主线程而不是子线程中运行函数。 您首先调用函数,然后再将返回的值作为线程目标。 您的代码应为:

thread1 = threading.Thread(target=fun1)
thread2 = threading.Thread(target=fun2)

然后您将获得预期的结果。

如果以交互方式运行代码,将获得以下输出

>>> import threading
>>> import time
>>> 
>>> def fun1():
...     testz=['z','y','x','w','v','u','t']
...     for j in testz:
...         print (j)
...         time.sleep(1)
... 
>>> def fun2():
...     test=['a','b','c','d','e','f','g']
...     for i in test:
...         print (i)
...         time.sleep(1)
... 
>>> 
>>> thread1 = threading.Thread(target=fun1())
z
y
x
w
v
u
t
>>> thread2 = threading.Thread(target=fun2())
a
b
c
d
e
f
g
>>> 
>>> thread1.start()
>>> time.sleep(0.5)
>>> thread2.start()
>>> 
>>> thread1.join()
>>> thread2.join()

您可以看到,一旦使用thread1 = threading.Thread(target=fun1())fun1()创建线程,就会执行fun1()
同样,为fun2()创建线程后,将立即执行该线程。
因此,这两个功能实际上并未并行运行,而您正在获得该输出。

在创建线程时,您将fun1 / fun2的结果作为目标而不是函数本身传递。 这就是为什么立即而不是在启动线程之后立即执行功能的原因。

尝试将您的线程创建替换为

thread1 = threading.Thread(target=fun1)
thread2 = threading.Thread(target=fun2)

您的代码存在以下问题:

thread1 = threading.Thread(target=fun1())
thread2 = threading.Thread(target=fun2())

在这里,它在主线程本身中被称为整体函数。 也就是说,两个函数都使用相同的threadID调用

<_MainThread(MainThread, started 4339086784)>
z
y
x
w
v
u
t
<_MainThread(MainThread, started 4339086784)>
a
b
c
d
e
f
g

正确地,用于创建线程对象的语法应为:

thread1 = threading.Thread(target=fun1)
thread2 = threading.Thread(target=fun2)

更改后:输出

z
a
y
b
x
c
w
d
v
e
u
f
t
g

线程处理不会使代码并行运行,而是提供了并行运行代码的错觉。 这属于并发的更大范围。

您正在创建两个线程。 线程将完成某些工作,并且操作系统可以随时将其关闭以将资源提供给另一个线程。 然后停止另一个线程,并继续第一个线程。 它将随机地执行此操作。

这些列表的打印元素发生得如此之快,以至于操作系统从未停止过该线程。 另外,请注意,使用螺纹打印可能会导致竞争。 从本质上讲,奇怪的行为可能很难调试。 做一些模糊测试,基本上为每个迭代添加一个带有随机数的sleepsleep(random.random()) ,您将看到这些竞争条件变得活跃起来。

如果要在问题中说明文字输出,可以执行以下操作:

from itertools import chain

for i in chain(*zip(list1, list2)):
    print(i)

您的第一个线程先结束,然后再开始第二个线程,因为您在那里已经睡着了,并且正在执行功能。 您应该将callable传递给线程(传递不带()的函数)。 您不能保证您的代码将按预期运行,并在每次执行中获得相同的结果。

如果不需要线程,则可以使用简单的zip:

for a, b in zip(list1, list2):
    print(a)
    print(b)

如果您确实需要多线程并且依次执行elist的每个元素,则可以查看Condition()来锁定线程,并使用acquire()和release()方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM