Python脚本中线程未并行运行

4

我是Python和线程方面的新手。我正在尝试同时运行多个线程。以下是我的基础代码:

  import threading
  import time
  threads = []

  print "hello"

  class myThread(threading.Thread):
          def __init__(self,i):
                  threading.Thread.__init__(self)
                  print "i = ",i
                  for j in range(0,i):
                          print "j = ",j
                          time.sleep(5)

  for i in range(1,4):
          thread = myThread(i)
          thread.start()

当一个线程等待 time.sleep(5) 时,我希望另一个线程开始运行。简而言之,所有线程应该并行运行。


1
据我所知,Python 中的线程都在单个核心上运行。因此,线程能做的唯一事情就是增加 CPU 的突发负载。如果要使用多个核心,您需要使用 multiprocessing 库来启动新进程。 - Willem Van Onsem
当线程被构造时,它在同一线程上。如果您希望代码并发运行,应将 time.sleep 放在 run 方法中,而不是构造函数中。 - n00dl3
你可能想看一下这个答案,了解如何使用threading。基本上,你根本不需要子类化Thread,但如果你这样做,请不要使用__init __()构造函数来执行应该被线程化的任务。 - ImportanceOfBeingErnest
@n00dl3,去掉time.sleep会发生什么?它会并行运行吗? - Utkarsh Patel
1
不,根据您展示的代码,所有操作都是顺序执行的,因为您在Thread的构造函数中执行工作,甚至在线程启动之前就已经执行了。 - ImportanceOfBeingErnest
3个回答

7
您可能对如何子类化threading.Thread存在一些误解,首先,__init__()方法在Python中大致代表构造函数,基本上每次创建实例时都会执行该方法,因此在您的情况下,当执行thread = myThread(i)时,它将阻塞直到__init__()结束。

然后,您应该将活动移动到run()中,这样当调用start()时,线程将开始运行。例如:

import threading
import time
threads = []

print "hello"

class myThread(threading.Thread):
    def __init__(self, i):
        threading.Thread.__init__(self)
        self.i = i

    def run(self):
        print "i = ", self.i
        for j in range(0, self.i):
            print "j = ",j
            time.sleep(5)

for i in range(1,4):
    thread = myThread(i)
    thread.start()

P.S. 由于 CPython 中存在 GIL,如果任务是 CPU 密集型的,则可能无法充分利用所有处理器的优势。


它正在运转,我终于明白了它的工作原理。非常感谢。 - Utkarsh Patel

3

以下是一个关于如何根据你的代码使用线程的示例:

import threading
import time
threads = []

print "hello"

def doWork(i):
    print "i = ",i
    for j in range(0,i):
        print "j = ",j
        time.sleep(5)

for i in range(1,4):
    thread = threading.Thread(target=doWork, args=(i,))
    threads.append(thread)
    thread.start()

# you need to wait for the threads to finish
for thread in threads:
    thread.join()

print "Finished"

2
import threading
import subprocess


def obj_func(simid):
    simid = simid
    workingdir = './' +str (simid) # the working directory for the simulation
    cmd = './run_delwaq.sh' # cmd is a bash commend to launch the external execution
    subprocess.Popen(cmd, cwd=workingdir).wait()


def example_subprocess_files():
    num_threads = 4
    jobs = []

    # Launch the threads and give them access to the objective function
    for i in range(num_threads):
        workertask = threading.Thread(target=obj_func(i))
        jobs.append(workertask)

    for j in jobs:
        j.start()

    for j in jobs:
        j.join()

    print('All the work finished!')


if __name__ == '__main__':
    example_subprocess_files()

这个方法对于我这种任务不是打印而是CPU密集型任务的情况不起作用。线程在串行中被排除。

请提供翻译的文本,不要进行解释。 - Anantha Raju C
我已经更新了上面的代码,使用了我自己的案例。对于每个线程,工作人员需要运行一个外部程序。我为每个外部程序创建了单独的文件夹,以便它们不会相互干扰。然而,当我检查结果时,我发现每个线程中的外部程序是串行运行而不是并行运行。 - LouisXW
我测试了@Shane发布的解决方案,用于我的问题(覆盖Threading.Thread类的子类中的run()方法)。它有效。但是,不太确定为什么我上面发布的替代方法无法工作。因为根据Threading.Thread文档,这两种方法都应该有效。 - LouisXW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接