Python 批量创建线程及threading.Thread类的常用函数及方法

article/2025/10/6 19:07:49

在《【Python】线程的创建、执行、互斥、同步、销毁》(点击打开链接)中介绍了Python中线程的使用,但是里面线程的创建,使用了很原始的方式,一行代码创建一条。其实,Python里是可以批量创建线程的。利用Python批量创建线程可以将之前的程序优化,具体请看如下的代码:

# -*-coding:utf-8-*-
import threading;
mutex_lock = threading.RLock();  # 互斥锁的声明
ticket = 100000;  # 总票数
# 用于统计各个线程的得票数
ticket_stastics=[];
   
class myThread(threading.Thread):  # 线程处理函数
    def __init__(self, name): 
        threading.Thread.__init__(self);  # 线程类必须的初始化
        self.thread_name = name;  # 将传递过来的name构造到类中的name
    def run(self):
        # 声明在类中使用全局变量
        global mutex_lock;
        global ticket;   
        while 1:
            mutex_lock.acquire();  # 临界区开始,互斥的开始
            # 仅能有一个线程↓↓↓↓↓↓↓↓↓↓↓↓             
            if ticket > 0:                
                ticket -= 1;
                # 统计哪到线程拿到票
                print "线程%s抢到了票!票还剩余:%d。" % (self.thread_name, ticket);                
                ticket_stastics[self.thread_name]+=1;                                     
            else:                
                break;
            # 仅能有一个线程↑↑↑↑↑↑↑↑↑↑↑↑
            mutex_lock.release();  # 临界区结束,互斥的结束
        mutex_lock.release();  # python在线程死亡的时候,不会清理已存在在线程函数的互斥锁,必须程序猿自己主动清理
        print "%s被销毁了!" % (self.thread_name);  
              
# 初始化线程 
threads = [];#存放线程的数组,相当于线程池
for i in range(0,5):
    thread = myThread(i);#指定线程i的执行函数为myThread
    threads.append(thread);#先讲这个线程放到线程threads
    ticket_stastics.append(0);# 初始化线程的得票数统计数组
for t in threads:#让线程池中的所有数组开始
    t.start(); 
for t in threads:
    t.join();#等待所有线程运行完毕才执行一下的代码
print "票都抢光了,大家都散了吧!";
print "=========得票统计=========";
for i in range(0,len(ticket_stastics)):
    print "线程%d:%d张" % (i,ticket_stastics[i]);

运行结果还是原来的功能:

 但是,这里利用了一个数组和for循环创建线程,先遍历创建一堆线程放到线程池threads里面,实质上所谓的“线程池”也就是存放线程的数组,再用一个for循环,让这个线程池threads里面的线程全部开始。

# 初始化线程 
threads = [];#存放线程的数组,相当于线程池
for i in range(0,5):
    thread = myThread(i);#指定线程i的执行函数为myThread
    threads.append(thread);#先讲这个线程放到线程threads
for t in threads:#让线程池中的所有数组开始
    t.start(); 
for t in threads:
    t.join();#等待所有线程运行完毕才执行一下的代码

待所有线程开始之后,再让主线程,也就是整个主程序,等待所有子线程thread结束才执行下面的代码。
这里不能写成如下的代码段:

for t in threads:#让线程池中的所有数组开始
    t.start();
    t.join();#等待所有线程运行完毕才执行一下的代码

这样的话,主程序会等待线程0,跑完myThread中的所有代码,才去创建线程1,2,3.....的,这样达不到线程并发的目的,程序变成单线程执行了,这是批量创建线程需要注意的地方。


有注释的详解

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import threading as td
import timedef threadJob():'''task01'''threadJob2()def threadJob2():'''task02'''print('create threading: %s'% td.current_thread())print ('T1 start')for i in range(10):time.sleep(0.1)print('T1 finish\n')def threadJob3():'''task03'''print('create threading: %s'% td.current_thread())print ('T2 start')print('T2 finish\n')def main(*args):# 创建线程,它要去运行threadJob 命名线程名称T1added_threading1 = td.Thread(target=threadJob,name='T1')# 创建第二个线程 执行task03 命名T3added_threading2 = td.Thread(target=threadJob3,name='T3')# 开始执行T1(与主线程同时执行)added_threading1.start()# 如果使用join() 会先执行完T1进程,再执行下面的程序,还有加载到主线程的意思added_threading1.join()# 开始执行T2added_threading2.start()# 如果使用join() 会先执行完T3进程,再执行下面的程序,还有加载到主线程的意思added_threading2.join()print('\nMian')# 有多少个激活的线程print(td.active_count())# 哪个线程print(td.enumerate())# 正在运行的是哪个线程print(td.current_thread())if __name__=='__main__':main()

python:threading.Thread类的使用详解


Python Thread类表示在单独的控制线程中运行的活动。有两种方法可以指定这种活动:
1、给构造函数传递回调对象

mthread=threading.Thread(target=xxxx,args=(xxxx))
mthread.start()


2、在子类中重写run() 方法
这里举个小例子:

import threading, time
class MyThread(threading.Thread):def __init__(self):threading.Thread.__init__(self)def run(self):global n, locktime.sleep(1)if lock.acquire():print n , self.namen += 1lock.release()
if "__main__" == __name__:n = 1ThreadList = []lock = threading.Lock()for i in range(1, 200):t = MyThread()ThreadList.append(t)for t in ThreadList:t.start()for t in ThreadList:t.join()


派生类中重写了父类threading.Thread的run()方法,其他方法(除了构造函数)都不应在子类中被重写,换句话说,在子类中只有_init_()和run()方法被重写。使用线程的时候先生成一个子线程类的对象,然后对象调用start()方法就可以运行线程啦(start调用run)

下面我们进入本文的正题threading.Thread类的常用函数与方法:

 

1、一旦线程对象被创建,它的活动需要通过调用线程的start()方法来启动。这方法再调用控制线程中的run方法。

2、一旦线程被激活,则这线程被认为是’alive’(活动)。当它的run()方法终止时-正常退出或抛出未处理的异常,则活动状态停止。isAlive()方法测试线程是否是活动的。大致上,线程从 start()调用开始那点至它的run()方法中止返回时,都被认为是活动的。模块函数enumerate()返回活动线程的列表。

3、一个线程能调用别的线程的join()方法。这将阻塞调用线程,直到拥有join()方法的线程的调用终止。

4、线程有名字,默认的是Thread-No形式的,名字能传给构造函数,通过setName()方法设置,用getName()方法获取。

5、线程能被标识为’daemon thread’(守护线程).这标志的特点是当剩下的全是守护线程时,则Python程序退出。它的初始值继承于创建线程。标志用setDaemon()方法设置,用isDaemon()获取。

6、存在’main thread’(主线程),它对应于Python程序的初始控制线程。它不是后台线程。

7、

class Thread(group=None, target=None, name=None, args=(), kwargs={})

 构造函数能带有关键字参数被调用。这些参数是:

group 应当为 None,为将来实现Python Thread类的扩展而保留。

target 是被 run()方法调用的回调对象. 默认应为None, 意味着没有对象被调用。

name 为线程名字。默认形式为’Thread-N’的唯一的名字被创建,其中N 是比较小的十进制数。

args是目标调用参数的tuple,默认为空元组()。

kwargs是目标调用的参数的关键字dictionary,默认为{}。

8、如果子线程重写了构造函数,它应保证调用基类的构造函数(Thread._init_()),在线程中进行其他工作之前。(也就是派生类刚开始就要调用基类的构造函数)

9、start()

启动线程活动。在每个线程对象中最多被调用一次。它安排对象的run() 被调用在一单独的控制线程中。

10、run()

用以表示线程活动的方法。你可能在Python Thread类的子类重写这方法。标准的 run()方法调用作为target传递给对象构造函数的回调对象。

11、join([timeout])

等待至线程中止。阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。

timeout参数不是None,它应当是浮点数指明以秒计的操作超时值。因为join()总是返回None,你必须调用isAlive()来判别超时是否发生。

当timeout 参数没有被指定或者是None时,操作将被阻塞直至线程中止。

线程能被join()许多次。

线程不能调用自身的join(),因为这将会引起死锁。

在线程启动之前尝试调用join()会发生错误。

12、

getName()

返回线程名。

setName(name)

设置线程名。

这名字是只用来进行标识目的的字符串。它没有其他作用。多个线程可以取同一名字。最初的名字通过构造函数设置。

 

isAlive()

返回线程是否活动的。

isDaemon()

返回线程的守护线程标志。

setDaemon(daemonic)

设置守护线程标志为布尔值daemonic。它必须在start()调用之前被调用。

当没有活动的非守护线程时,整个Python程序退出。


http://chatgpt.dhexx.cn/article/cTSXsTWZ.shtml

相关文章

功能强大的python包(十一):threading (多线程)

1.threading简介 threading库是python的线程模型,利用threading库我们可以轻松实现多线程任务。 2.进程与线程简介 通过上图,我们可以直观的总结出进程、线程及其之间的关系与特点: 进程是资源分配的最小单元,一个程序至少包含…

一文搞明白Python多线程编程:threading库

目录 前言一、基础知识1、并行和并发(1)定义(2)联系 2、进程和线程(1)定义(2)联系 3、全局解释器锁GIL 二、threading库1、线程的使用(1)普通创建方式&#x…

分块矩阵求逆(推导)

关于分块矩阵求逆,其中对角矩阵比较简单,我看很多人都写了,并且很详细。 但关于AUVD的分块矩阵我没看到太让我明白的,可能我get不到点,数学基础差,我就自己写了详细的步骤。 我写的这个条件是A可逆&#…

伴随矩阵求逆矩阵

在之前的文章《线性代数之矩阵》中已经介绍了一些关于矩阵的基本概念,本篇文章主要就求解逆矩阵进行进一步总结。 余子式(Minor) 我们先看例子来直观的理解什么是余子式(Minor,后边将都用英文Minor,中文的翻译较乱)。 minor exa…

矩阵的逆

矩阵的逆 原理&#xff1a; 连接&#xff1a; https://baike.baidu.com/item/%E9%80%86%E7%9F%A9%E9%98%B5 代码&#xff1a; QT c版&#xff1a; //求逆矩阵 QVector<QVector<double>> Matrix_inverse(QVector<QVector<double>> &A) {int …

矩阵求逆

矩阵求逆 初等变换求逆参考文章 初等变换求逆 1&#xff09;初等变换求逆矩阵时不能同时使用初等列变换和初等行变换&#xff0c;使用初等列变换或者初等行变换来求逆矩阵都是可以的&#xff0c;但是不能二者同时使用&#xff0c;只能用一种方法来得到逆矩阵。 2&#xff09;初…

卡西欧计算器矩阵求逆

记录一下&#xff0c;防止忘记 1 按开机键 打开计算器 2 按 菜单设置键 进去计算模式选择模块 3 按“ 4 ”选择矩阵运算 4 有四个矩阵可以编辑 选择按 4 编辑矩阵D 5 输入矩阵的行数 我按了3 6 输入矩阵的列数 我按了 3 7 建了一个3*3空矩阵 输入第一个数 12 然后按“”键完…

如何用计算机求矩阵的逆矩阵,逆矩阵的求法

逆矩阵是数学知识的一种&#xff0c;很多学习数学的同学们应该很了解吧。逆矩阵计算器是一款可以对矩阵的逆进行计算的免费程序,本程序引入了分数算法,可以对分数元素计算并得出分数结果。那么这款软件怎么样呢&#xff1f;接下来&#xff0c;介绍一下。 逆矩阵的求法 A^(-1)(1…

python求逆矩阵的方法,Python 如何求矩阵的逆

我就废话不多说了,大家还是直接看代码吧~ import numpy as np kernel = np.array([1, 1, 1, 2]).reshape((2, 2)) print(kernel) print(np.linalg.inv(kernel)) 注意,Singular matrix奇异矩阵不可求逆 补充:python+numpy中矩阵的逆和伪逆的区别 定义: 对于矩阵A,如果存在一…

Maple矩阵求逆

如何使用Maple进行矩阵求逆 调用包 with(LineAlgebra);输入我想要的矩阵&#xff1a; R : Matrix([[cos(a), sin(a), 0], [-sin(a), cos(a), 0], [0, 0, 1]]);然后我使用了Inverse命令 simplify(Inverse(R));结果并没有生成矩阵的逆。 查了一下说明手册加上mod好像也不行&a…

线性代数 --- 矩阵求逆的4种方法

线性代数 --- 矩阵求逆的4种方法 写在最前面&#xff1a;在大多数情况下&#xff0c;我们学习线性代数的目的是为了求解线性方程组Axb&#xff0c;而不是为了求A的逆。 单就解方程而言&#xff0c;LU分解是最实用的算法。只需按照ALU——>Axb,LUxb——>Lyb(正向回代求得y…

求解逆矩阵的常用三种方法

1.待定系数法 矩阵A 1, 2 -1,-3 假设所求的逆矩阵为 a,b c,d 则 从而可以得出方程组 a 2c 1 b 2d 0 -a - 3c 0 -b - 3d 1 解得 a3; b2; c -1; d -1 2.方程组求逆矩阵 伴随矩阵是矩阵元素所对应的代数余子式&#xff0c;所构成的矩阵&#xff0c;转置后得到的新矩阵。 …

矩阵求逆四种方法

注&#xff1a; 用A、B表示某矩阵, E表示单位矩阵 用Aˊ表示A逆 用|A|表示A的行列式 &#xff3b;A|E&#xff3d;表示拼接矩阵 一、公式法 先求A行列式结果&#xff0c;再求A伴随矩阵&#xff0c;最后再求A逆矩阵 |A| &#xff01; 0 则 AˊA*/|A| 注&#xff1a;图片中det…

浏览器渲染页面和加载页面机制

为什么有些网站打开的时候会加载会很慢&#xff0c;而且是整个页面同时显示的&#xff0c;而有些网站是从顶到下逐步显示出来的&#xff1f;弄懂这些对前端性能优化有很大帮助。要搞懂这个可以先从下面这个常规流程开始&#xff1a; 常规流程 1. 浏览器下载的顺序是从上到下&am…

页面实现加载进度条

文章目录 一、定时器实现进度条二、css3实现进度条三、加载状态事件实现进度条 一、定时器实现进度条 原理&#xff1a;设置了固定的时间后将图片和遮罩层隐藏,显示出页面的内容 效果1&#xff1a; 定时器实现的进度条效果 代码实现 <!DOCTYPE html> <html langen>…

VUE页面中加载外部HTML

方法1&#xff0c;用iframe vue页面 <template><button click"invokeHtmlMethod">调用html种方法</button><div class"iframestyleset"><iframe name "iframeMap" id"iframeMapViewComponent" v-bind…

页面还未加载完成显示loading

页面未加载完成&#xff0c;显示loading的图标 html代码 <div id"loading"><i></i> </div> css 代码 #loading{width: 100%;height: 100%;background-color: #fff;position: fixed;top:0;left: 0;z-index: 9999; }#loading >i{width: …

浏览器加载页面的过程

开源浏览器一般以8k每块下载html页面。 1、然后解析页面生成DOM树&#xff0c; 2、遇到css标签或JS脚本标签就新起线程去下载他们&#xff0c;并继续构建DOM。 3、下载完后解析CSS为CSS规则树&#xff0c;浏览器结合CSS规则树和DOM树生成Render Tree。 注意&#xff1a;构建…

浏览器加载网页过程

1.概要&#xff1a;从用户在浏览器输入域名开始&#xff0c;到web页面加载完毕&#xff0c;这个过程叫做网页加载过程&#xff0c;个人总结&#xff0c;长期更新 2.分析&#xff1a;打开一个网页&#xff0c;浏览器会因为页面上的css/js/image等静态资源多次发起连接请求&#…

登录页面加载效果

说明&#xff1a;我们在做后台管理系统的时候&#xff0c;都会有一个登录页面&#xff0c;有的时候网速比较慢&#xff0c;登录速度比较慢&#xff0c;有的用户就会一直点登录按钮&#xff08;图1&#xff09;&#xff0c;体验不是特别好&#xff0c;基于此&#xff0c;优化一下…