线程
一. 线程
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,
是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中
,进程是线程的容器。程序是指令、数据及其组织形式的描述,
进程是程序的实体。
线程: 是程序中一个单一的顺序控制流程。进程内有一个相对独立的、
可调度的执行单元,是系统独立调度和分派CPU的基本单位指令运行
时的程序的调度单位。
在单个程序中同时运行多个线程完成不同的工作,称为多线程。
进程一般有三个状态:就绪状态、执行状态和等待状态【或称阻塞状态】;
进程只能由父进程建立,系统中所有的进程形成一种进程树的层次体系;
挂起命令可由进程自己和其他进程发出,但是解除挂起命令只能由其他进程发出。
进程一般有三个状态:就绪状态、执行状态和等待状态【或称阻塞状态】
;进程只能由父进程建立,系统中所有的进程形成一种进程树的层次体系
;挂起命令可由进程自己和其他进程发出,但是解除挂起命令只能由其他进程发出。
在一个进程内部 要同时干多件事 就需要同时运行多个子任务
我们把进程内的这些子任务叫线程
线程通常叫做轻型的进程 线程是共享内存空间的 并发执行的多任务,每一个线程
都共享一个进程的资源
线程是最小的执行单元 而进程由至少一个线程组成 如何调度进程和线程
完全有操作系统绝对 程序自己不能决定什么时候执行 执行多长的时间
模块:
1._thraed 模块 低级模块(意思接近底层c语言)
2.threading 模块 高级模块 对_thraed进行了
启动一个线程
import threading,time def run(): print("子线程(%s)开始"%(threading.current_thread().name)) # 实现线程功能 print("打印了") time.sleep(2) print("子线程(%s)结束"%(threading.current_thread().name)) if __name__ == '__main__': # 任何进程默认就会启动一个线程 称为主线程 主线程可以器动新的子线程 # current_thread() #返回当前线程的实例 在哪个线程里面就返回哪个线程的实例 print("主线程(%s)启动"%(threading.current_thread().name)) # 打印当前线程名称 # 01创建子线程 # target=run执行指定代码 # name 是指线程名称 t=threading.Thread(target=run,name="rooTHread") # 线程执行 t.start() print("主线程(%s)结束"%(threading.current_thread().name)) # 打印当前线程名称 主线程(MainThread)启动 子线程(rooTHread)开始 主线程(MainThread)结束 打印了 子线程(rooTHread)结束
启动一个线程
import threading,time aa=100000000000000000000000 def run(): print("子线程(%s)开始"%(threading.current_thread().name)) # 实现线程功能 print("打印了") time.sleep(2) print(aa) print("子线程(%s)结束"%(threading.current_thread().name)) if __name__ == '__main__': # 任何进程默认就会启动一个线程 称为主线程 主线程可以器动新的子线程 # current_thread() #返回当前线程的实例 在哪个线程里面就返回哪个线程的实例 print("主线程(%s)启动"%(threading.current_thread().name)) # 打印当前线程名称 # 01创建子线程 # target=run执行指定代码 # name 是指线程名称 t=threading.Thread(target=run,name="rooTHread") # 线程执行 t.start() # 等待线程结束 t.join() print("主线程(%s)结束"%(threading.current_thread().name)) # 打印当前线程名称 # 主线程(MainThread)启动 # 子线程(rooTHread)开始 # 打印了 # 100000000000000000000000 # 子线程(rooTHread)结束 # 主线程(MainThread)结束
启动一个线程传值
import threading,time aa=100000000000000000000000 def run(num): print("子线程(%s)开始"%(threading.current_thread().name)) # 实现线程功能 print("打印了",num) time.sleep(2) print(aa) print("子线程(%s)结束"%(threading.current_thread().name)) if __name__ == '__main__': # 任何进程默认就会启动一个线程 称为主线程 主线程可以器动新的子线程 # current_thread() #返回当前线程的实例 在哪个线程里面就返回哪个线程的实例 print("主线程(%s)启动"%(threading.current_thread().name)) # 打印当前线程名称 # 01创建子线程 # target=run执行指定代码 # name 是指线程名称 t=threading.Thread(target=run,name="rooTHread",args=(1111110000,)) # 线程执行 t.start() # 等待线程结束 t.join() print("主线程(%s)结束"%(threading.current_thread().name)) # 打印当前线程名称 # 主线程(MainThread)启动 # 子线程(rooTHread)开始 # 打印了 1111110000 # 100000000000000000000000 # 子线程(rooTHread)结束 # 主线程(MainThread)结束
线程间是共享数据但是数据会乱
import threading,time """多线程和多进程最大的不同在于 多进程中 同一个变量 各自有一份拷贝存在每个进程中 互相不影响 而多线程 所有变量都有所有线程共享 所以任何一个变量都可以被任意 一个线程修改 因此 线程之间共享数据最大的危险在于多个线程同时修改一个变量 容易吧内容改乱 """ aa=0 def run(n): for i in range(1000000): global aa aa=aa+n #15=9+5 aa=aa-n #9 if __name__ == '__main__': t1=threading.Thread(target=run,args=(6,)) t2=threading.Thread(target=run,args=(9,)) t1.start() t2.start() t1.join() t2.join() print("aa:",aa) # 线程1 aa=aa+6 # aa-6=3 # 线程2 aa=aa+9 # 3-9=-6
使用线程锁解决数据混乱
""" 两个线程同时工作 一个存钱 一个取钱 可能导致数据异常 思路:加锁 能解决数据乱的问题 """ import threading,time # 锁对象 lock=threading.Lock() aa=0 def run(n): for i in range(1000000): global aa # 加锁 # 确保了这段代码只能由一个线程从头到尾的完整性 从而保持了数据不会乱 # 加锁因为阻止了多线程的并发 包含锁的某段代码实际上只能以单线程模式执行 # 从而效率降低了 要比单线程快点 # 由于他可以存在多个锁 不同线程持有不同的锁 有可能试图获取其它的锁 # 可能造成死锁 导致多个线程挂起 只能靠操作系统了强制终止 lock.acquire() try: aa=aa+n #15=9+5 aa=aa-n #9 finally: # 修改完一定要释放锁 lock.release() if __name__ == '__main__': t1=threading.Thread(target=run,args=(6,)) t2=threading.Thread(target=run,args=(9,)) t1.start() t2.start() t1.join() t2.join() print("aa:",aa) """# 与上面的代码功能相同 with look 可以自动上锁 解锁 # 只是这样可以降低死锁的概率 with lock: aa=aa+n aa=aa-n """
threadlocal
import threading num=0 """创建一个全局的thraedlocal 每个线程有独有的存储空间 每个线程threading对象都可以读写 但是互不影响""" local=threading.local() def run(x,n): # 每个线程都有local.x 就是线程的局部变量 x=x+n x=x-n def func(n): local.x=num for i in range(100000): run(local.x,n) print(threading.current_thread().name,local.x) if __name__ == '__main__': t1=threading.Thread(target=func,args=(6,)) t2=threading.Thread(target=func,args=(9,)) t1.start() t2.start() t1.join() t2.join() print("aa:",num) """Thread-1 0 Thread-2 0 aa: 0 """ """ 作用 :为每一个线程绑定一个数据库连接 或者http请求 这样一个线程的所有 调用到的处理函数都可以非常方便访问这些资源 """
信号量控制线程数量
import threading,time sem=threading.Semaphore(3) # 控制线程的数量 意思三个三个线程走 def run(): with sem: for i in range(10): print(threading.current_thread().name,i) time.sleep(2) if __name__=="__main__": for i in range(5): threading.Thread(target=run).start()
凑够一定数量才能一起执行
import threading,time bar=threading.Barrier(4) # 凑够四个线程才往下执行 def run(): print("开始",threading.current_thread().name) time.sleep(2) bar.wait() print("结束",threading.current_thread().name) if __name__=="__main__": for i in range(5): threading.Thread(target=run).start() # 开始 Thread-1 # 开始 Thread-2 # 开始 Thread-3 # 开始 Thread-4 # 开始 Thread-5 # 结束 Thread-2 # 结束 Thread-1 # 结束 Thread-4 # 结束 Thread-3 # 结束 Thread-5
定时线程
import threading,time def run(): print("开始444444444") t=threading.Timer(5,run) t.start() t.join() print("延时执行结束")
线程通讯
import threading,time def func(): # 事件对象 event=threading.Event() def run(): for i in range(5): # 阻塞等待事件的触发 event.wait() # 重置 event.clear() print("哈哈哈哈哈哈哈哈或") t=threading.Thread(target=run).start() return event e=func() # 触发事件 for i in range(5): time.sleep(2) e.set()
生产者和消费者
import threading,time,queue,random """ 生产者 : 生产数据 消费者 : 处理数据 """ # 生产者 def product(id,q): while True: num=random.randint(0,100) q.put(num) print("生产者生产了数据放入了队列",id,num) time.sleep(5) # 任务完成 q.task_dome() # 消费者 def customer(id,q): while True: item=q.get() if item is None: break print("消费者消费数据",id,item) time.sleep(5) # 完成任务 q.task_dome() if __name__=="__main__": # 消息列队 q=queue.Queue() # 启动生产者 for i in range(4): threading.Thread(target=product,args=(i,q)).start() # 启动消费者 for i in range(3): threading.Thread(target=customer,args=(i,q)).start() 生产者生产了数据放入了队列 0 92 生产者生产了数据放入了队列 1 3 生产者生产了数据放入了队列 2 51 生产者生产了数据放入了队列 3 54 消费者消费数据 0 92 消费者消费数据 1 3 消费者消费数据 2 51 生产者生产了数据放入了队列 0 98 生产者生产了数据放入了队列 2 83 生产者生产了数据放入了队列 1 40 生产者生产了数据放入了队列 3 7 消费者消费数据 0 54 消费者消费数据 1 98 消费者消费数据 2 83 生产者生产了数据放入了队列 0 73 生产者生产了数据放入了队列 2 53 生产者生产了数据放入了队列 1 51 生产者生产了数据放入了队列 3 20 消费者消费数据 0 40 消费者消费数据 1 7 消费者消费数据 2 73
二. 进程案例
1. 线程客服端与服务器端的交互
client客服端.py
import socket client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(("192.168.100.111",8082)) while True: data=input("请输入给服务器的数据") client.send(data.encode("utf-8")) info=client.recv(1024) print(info.decode("utf-8"))
client客服端1.py
import socket client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(("192.168.100.111",8082)) count=0 while True: count+=1 data=input("请输入给服务器的数据") client.send(data.encode("utf-8")) info=client.recv(1024) print(info.decode("utf-8"))
server服务器.py
import socket import threading # 01创建服务器socket server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 02绑定端口和ip server.bind(('192.168.100.111',8082)) # 03监听 server.listen(5) print("启动成功了.................") def run(ck): data=clientSocket.recv(1024) print("客服端说:"+data.decode("utf-8")) # sendData=input("输入返回给客服端的信息:") clientSocket.send("大美女来了哈哈哈哈哈".encode("utf-8")) print("服务接受成功了哈哈哈哈") while True: # 04等待连接 clientSocket,clientAddress=server.accept() # print(str(clientSocket),clientAddress,"哈哈哈哈哈哈哈哈去") t=threading.Thread(target=run,args=(clientSocket,)) t.start()
2. 线程客服端与服务器端的交互聊天
client客服端.py
import socket client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(("192.168.100.111",8082)) while True: data=input("请输入给服务器的数据") client.send(data.encode("utf-8")) info=client.recv(1024) print(info.decode("utf-8"))
client客服端1.py
import socket client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(("192.168.100.111",8082)) count=0 while True: count+=1 data=input("请输入给服务器的数据") client.send(data.encode("utf-8")) info=client.recv(1024) print(info.decode("utf-8"))
server服务器.py
import socket import threading # 01创建服务器socket server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 02绑定端口和ip server.bind(('192.168.100.111',8082)) # 03监听 server.listen(5) print("启动成功了.................") def run(ck): data=clientSocket.recv(1024) print("客服端说:"+data.decode("utf-8")) # sendData=input("输入返回给客服端的信息:") clientSocket.send("大美女来了哈哈哈哈哈".encode("utf-8")) print("服务接受成功了哈哈哈哈") while True: # 04等待连接 clientSocket,clientAddress=server.accept() # print(str(clientSocket),clientAddress,"哈哈哈哈哈哈哈哈去") t=threading.Thread(target=run,args=(clientSocket,)) t.start()