04线程
一、线程的引入
如果说在操作系统中引入进程的目的是使多个程序并发执行,以改善资源利用率及提高系统吞吐量,那么在操作系统中再引入线程则是为了
减少程序并发执行所付出的时空开销,使操作系统具有更好的并发性。
进程的两个基本属性:
1、进城是一个拥有资源的独立单位
2、进程同时又是一个可以被处理器,单独调度和分配的单元
为了使进程能并发执行,操作系统还必须进行一系列的操作,如创建进程、撤销进程和进程切换,在进行这些操作时操作系统要为进程分配
资源及回收资源为运行进程保存现场信息,这些工作都需要付出较多的时空开销,
正因如此在系统中不易设置过多的进程,进程的切换频率也不宜太高,从而限制了系统并发程度。
为了使多个程序更好的并发执行并尽量减少操作系统的开销,操作系统将进行了两个属性分离开来,分别有不同的实体来实现,
让线程去完成第2个基本属性,而进程只完成第1个基本属性的任务。
二、创建线程的两种方式
(1)方法一
from threading import Thread import time, random def fun(name): print('{} is starting,'.format(name)) time.sleep(random.randint(1,3)) print('{} is done'.format(name)) if __name__ == '__main__': t = Thread(target=fun, args=('cc', )) t.start() print('主')
(2)方法二
class MyThread(Thread): def __init__(self, name): super().__init__() self.name = name def run(self): print('{} is starting,'.format(self.name)) time.sleep(random.randint(1, 3)) print('{} is done'.format(self.name)) if __name__ == '__main__': t = MyThread('cc') t.start() print('主')
例1、多线程实现并发的套接字通信
# 服务器端 from threading import Thread, current_thread from socket import * from time import ctime def communicate(conn): print('子线程,',current_thread().getName()) while True: try: data = conn.recv(1024) if not data: break print('recv:', data.decode('utf-8')) conn.send(('[{}] {}'.format(ctime(), data)).encode('utf-8')) except Exception: break conn.close() def server(ip,port): print('主线程,', current_thread().getName()) tcpSerSock = socket(AF_INET, SOCK_STREAM) tcpSerSock.bind((ip, port)) tcpSerSock.listen(5) while True: print('waiting for connecting....') conn, addr = tcpSerSock.accept() print('connecting from :', addr) # communicate(conn) t = Thread(target=communicate, args=(conn, ))#利用多线程解决并发问题 t.start() tcpSerSock.close() if __name__ == '__main__': server('127.0.0.1', 3000)
# 客户端 from socket import * from time import ctime tcpCliSock = socket(AF_INET, SOCK_STREAM) tcpCliSock.connect(('127.0.0.1', 3000)) while True: data = input('please input:') if not data: continue tcpCliSock.send(data.encode('utf-8')) data = tcpCliSock.recv(1024) print('recv:',data.decode('utf-8')) tcpCliSock.close()
例2、三个任务,一个接收用户输入,一个将用户输入的内容格式化成大写,一个将格式化后的结果存入文件
from threading import Thread msg_l = [] format_l = [] def recv_input(): while True: msg = input('please input:') if not msg:continue msg_l.append(msg) def str_to_upper(): while True: if msg_l: res = msg_l.pop() format_l.append(res.upper()) def save(): while True: if format_l: with open('data.txt', 'a') as f: res = format_l.pop() f.write(res+'\n') if __name__ == '__main__': t1 = Thread(target=recv_input) t2 = Thread(target=str_to_upper) t3 = Thread(target=save) t1.start() t2.start() t3.start()
三、守护线程:等待所有的非守护线程结束后它才结束
from threading import Thread import time def fun1(): print('123 start...') time.sleep(3) print('123 end...') def fun2(): print('456 start...') time.sleep(1) print('456 end...') if __name__ == '__main__': t1 = Thread(target=fun1) t2 = Thread(target=fun2) t1.daemon = True t1.start() t2.start() print('主线程。。。')
四、线程相关的其他方法
Thread实例对象的方法
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
threading模块提供的一些方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】