Python3 与 C# 并发编程之~ 线程篇1
时间:2022-06-10
本文章向大家介绍Python3 与 C# 并发编程之~ 线程篇1,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
2.线程篇
示例代码:https://github.com/lotapp/BaseCode/tree/master/python/5.concurrent/Thread
终于说道线程了,心酸啊,进程还有点东西下次接着聊,这周4天外出,所以注定发文少了 +_+
用过Java或者Net的重点都在线程这块,Python的重点其实在上篇,但线程自有其独到之处~比如资源共享(更轻量级)
这次采用循序渐进的方式讲解, 先使用,再深入,然后扩展,最后来个案例
,呃.呃.呃.先这样计划~欢迎纠正错误
2.1.入门篇
官方文档:https://docs.python.org/3/library/threading.html
进程是由若干线程组成的(一个进程至少有一个线程)
2.1.1.线程案例
用法和 Process
差不多,咱先看个案例: Thread(target=test,args=(i,))
import osfrom threading import Thread, current_thread def test(name): # current_thread()返回当前线程的实例 thread_name = current_thread().name # 获取线程名 print(f"[编号:{name}],ThreadName:{thread_name}nPID:{os.getpid()},PPID:{os.getppid()}")def main(): t_list = [Thread(target=test, args=(i, )) for i in range(5)] for t in t_list: t.start() # 批量启动 for t in t_list: t.join() # 批量回收 # 主线程 print(f"[Main]ThreadName:{current_thread().name}nPID:{os.getpid()},PPID:{os.getppid()}")if __name__ == '__main__': main()
输出:(同一个进程ID)
[编号:0],ThreadName:Thread-1PID:20533,PPID:19830[编号:1],ThreadName:Thread-2PID:20533,PPID:19830[编号:2],ThreadName:Thread-3PID:20533,PPID:19830[编号:3],ThreadName:Thread-4PID:20533,PPID:19830[编号:4],ThreadName:Thread-5PID:20533,PPID:19830[Main]ThreadName:MainThreadPID:22636,PPID:19830
注意一点:Python里面的线程是Posix Thread
2.1.2.指定线程名
如果想给线程设置一个Div的名字呢?:
from threading import Thread, current_threaddef test(): # current_thread()返回当前线程的实例 print(f"ThreadName:{current_thread().name}")def main(): t1 = Thread(target=test, name="小明") t2 = Thread(target=test) t1.start() t2.start() t1.join() t2.join() # 主线程 print(f"[Main],ThreadName:{current_thread().name}")if __name__ == '__main__': main()
输出:(你指定有特点的名字,没指定就使用默认命令【联想古时候奴隶名字都是编号,主人赐名就有名了】)
ThreadName:小明ThreadName:Thread-1[Main],ThreadName:MainThread
类的方式创建线程
from threading import Threadclass MyThread(Thread): def __init__(self, name): # 设个坑,你可以自行研究下 super().__init__() # 放在后面就报错了 self.name = name def run(self): print(self.name)def main(): t = MyThread(name="小明") t.start() t.join()if __name__ == '__main__': main()
输出:(和Thread初始化的name冲突了【变量名得注意哦】)
小明
2.1.3.线程池案例
from multiprocessing.dummy import Pool as ThreadPool, current_processdef test(i): # 本质调用了:threading.current_thread print(f"[编号{i}]{current_process().name}")def main(): p = ThreadPool() for i in range(5): p.apply_async(test, args=(i, )) p.close() p.join() print(f"{current_process().name}")if __name__ == '__main__': main()
输出:
[编号0]Thread-3[编号1]Thread-4[编号3]Thread-2[编号2]Thread-1[编号4]Thread-3MainThread
微微扩展一下
对上面代码,项目里面一般都会这么优化:(并行这块线程后面会讲,不急)
from multiprocessing.dummy import Pool as ThreadPool, current_processdef test(i): # 源码:current_process = threading.current_thread print(f"[编号{i}]{current_process().name}")def main(): p = ThreadPool() p.map_async(test, list(range(5))) p.close() p.join() print(f"{current_process().name}")if __name__ == '__main__': main()
输出:
[编号0]Thread-2[编号1]Thread-4[编号2]Thread-3[编号4]Thread-2[编号3]Thread-1MainThread
代码改动很小(循环换成了map)性能提升很明显(密集型操作)
2.1.4.其他扩展
Thread初始化参数:
- daemon:是否为后台线程(主进程退出后台线程就退出了)
Thread实例对象的方法:
- isAlive(): 返回线程是否活动的
- getName(): 返回线程名
- setName(): 设置线程名
- isDaemon():是否为后台线程
- setDaemon():设置后台线程
threading模块提供的一些方法:
- threading.currentThread(): 返回当前的线程实例
- threading.enumerate(): 返回一个包含正在运行的线程List(线程启动后、结束前)
- threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
看一个小案例:
import timefrom threading import Thread, active_countdef test1(): print("test1") time.sleep(1) print("test1 ok")def test2(): print("test2") time.sleep(2) print("test2 ok")def main(): t1 = Thread(target=test1) t2 = Thread(target=test2, daemon=True) t1.start() t2.start() t1.join() print(active_count()) print(t1.is_alive) print(t2.is_alive) # t2.join() # 除非加这一句才等daemon线程,不然直接不管了if __name__ == '__main__': main()
下次就以 multiprocessing.dummy
模块为例了,API和 threading
几乎一样,进行了一些并发的封装,性价比更高
- Apache、struts1、struts2文件上传下载的3种方式
- 解析实时的DB time过程分析(r6笔记第35天)
- sql嵌入html格式显示报表(r6笔记第34天)
- hive计算日期差函数datediff,hive修改日期连接符
- 深度学习界的 “吃鸡挂”——目标检测 SSD 实验
- Hadoop查看所有JOB以及如何Kill指定用户的所有Job
- Java基础-23(01)总结多线程,线程实现Runnable接口,线程名字获取和设置,线程控制,线程安全,同步线程
- ORA-01427问题的分析和解决(r6笔记第51天)
- 从编程实现角度学习 Faster R-CNN(附极简实现)
- Java基础-23(02)总结多线程,线程实现Runnable接口,线程名字获取和设置,线程控制,线程安全,同步线程
- 8 个最好的 Java RESTful 框架
- 【C++基础】C++11 lambda 表达式解析
- 大量redo生成的问题原因及改进(r6笔记第50天)
- Java基础-22总结登录注册IO版,数据操作流,内存操作流,打印流,标准输入输出流,
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- (21)Bash用户自定义变量
- python实现支持向量机之具体实现
- Spring boot 集成apollo达到配置的热加载
- ApplicationContext 和beanFactory 和 factoryBean的区别以及联系
- pytorch中的nn.Embedding
- redis的持久化存储AOF的原理
- (三十四)golang--接口
- 回溯法--八皇后问题
- (19)Bash多命令顺序执行与管道符
- (三十五)golang--面向对象之多态
- redis的持久化存储RDB的原理分析
- BIO到NIO的演变过程
- tensorflow版本的tansformer训练IWSLT数据集
- final关键字你真的会用?
- golang实战--家庭收支记账软件(面向过程)