从 python3 的列表中启动 threading.Thread 对象的区别

Posted

技术标签:

【中文标题】从 python3 的列表中启动 threading.Thread 对象的区别【英文标题】:Difference in starting threading.Thread objects from a list in python3 【发布时间】:2022-01-21 13:26:05 【问题描述】:

我正在尝试做一个关于在 python 中使用多线程的练习。这是任务“编写一个程序,将两个或多个线程共享的计数器递增到某个阈值。考虑您可以使用的各种线程数以及各种初始值和阈值。每个线程将计数器的值增加一,如果低于阈值,则每 2 秒一次。”

我解决问题的尝试如下:

 from threading import Thread
import threading
import time

lock = threading.Lock()

class para:
    def __init__(self, value):
        self.para = value

class myT(Thread):
    def __init__(self,nome,para, end, lock):
        Thread.__init__(self)
        self.nome = nome
        self.end = end
        self.para = para
        self.lock = lock
    def run(self):
        while self.para.para < self.end:
            self.lock.acquire() 
            self.para.para += 1
            self.lock.release()
            time.sleep(2)
            print(self.nome, self.para.para)
            
        
         
para = para(1)

threads = []
for i in range(2):
    t = myT('Thread' + str(i), para, 15, lock)
    threads.append(t)

for i in range(len(threads)):
    threads[i].start()
    threads[i].join()

print('End code')

I have found an issue:
for i in range(len(threads)):
        threads[i].start()
        threads[i].join()

for 循环只启动一个线程,而其他线程未启动(实际上,输出只是名称为 'Thread0' 的线程增加变量。而如果我手动输入:

threads[0].start()
threads[1].start()
threads[0].join()
threads[1].join()

我得到了正确的输出,这意味着两个线程同时工作

在 for 之外编写 join 并为 join 实现 for 似乎可以解决问题,但我不完全明白为什么:

for i in range(len(threads)):
    threads[i].start()
for i in range(len(threads)):
    threads[i].join()

我想在这里请求解释在python中使用多线程解决任务的正确方法

【问题讨论】:

join() 将等待线程完成。因此,您不能在同一个循环中使用 start+join。否则,我们将只启动 1 个线程,然后等待它完成。对于您的任务,您希望多个线程正在运行,因此您必须多次调用start,并且不要等待任何线程完成,直到它们全部启动。因此,如上一个代码所示,有 2 个循环是正确的。 【参考方案1】:

这是对您的代码的编辑和一些观察。

线程共享相同的内存空间,因此无需将引用传递给 Lock 对象 - 可以在全局空间中。

Lock 对象支持 enterexit,因此可以用于工作经理的风格。

在第一个循环中,我们构建所有线程的列表并启动它们。一旦他们都开始了,我们使用另一个循环来加入他们。

所以现在看起来像这样:

from threading import Thread, Lock

class para:
    def __init__(self, value):
        self.para = value


class myT(Thread):
    def __init__(self, nome, para, end):
        super().__init__()
        self.nome = nome
        self.end = end
        self.para = para

    def run(self):
        while self.para.para < self.end:
            with LOCK:
                self.para.para += 1
            print(self.nome, self.para.para)


para = para(1)
LOCK = Lock()
threads = []
NTHREADS = 2

for i in range(NTHREADS):
    t = myT(f'Thread-i', para, 15)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

print('End code')

【讨论】:

以上是关于从 python3 的列表中启动 threading.Thread 对象的区别的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Python3 的列表中调用我自己的方法?

Python 3 ValueError 从列表中删除

Python3基础 list del 从内存中删除整个列表

如何从包含Python3中特定索引和列的列表的dict创建Pandas DataFrame?

Python3中列表的使用

Python3.7之列表与元组