一、进程理论
1)进程介绍
1、什么是进程 一个正在进行的过程,或者说是一个程序的运行过程 其实进程是对正在运行的程序的一种抽象/概括的说法 进程的概念起源操作系统,进程是操作最核心的概念之一 操作系统其他所有的概念都是围绕进程展开的 2、多道路技术 产生背景:针对单核,实现并发 ps: 现在的主机一般是多核,那么每个核都会利用多道技术 有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再重新调度,会被调度到4个 cpu中的任意一个,具体由操作系统调度算法决定。 2.空间上的复用:如内存中同时有多道程序 3.时间上的复用:复用一个cpu的时间片 强调:遇到io切,占用cpu时间过长也切,核心在于切之前将进程的状态保存下来,这样 才能保证下次切换回来时,能基于上次切走的位置继续运行 3、并发vs并行 并发(单核就可以实现并发) 多个任务看起来是同时运行的就是并发 并发的实现=切换+保存状态 并行(只有多核才能实现并行) 真正意义上的同时运行
2)进程状态
tail -f access.log |grep '404' 执行程序tail,开启一个子进程,执行程序grep,开启另外一个子进程,两个进程之间基于管道'|'通讯,将tail的结果作为grep的输入。 进程grep在等待输入(即I/O)时的状态称为阻塞,此时grep命令都无法运行 其实在两种情况下会导致一个进程在逻辑上不能运行, 1. 进程挂起是自身原因,遇到I/O阻塞,便要让出CPU让其他进程去执行,这样保证CPU一直在工作 2. 与进程无关,是操作系统层面,可能会因为一个进程占用时间过多,或者优先级等原因,而调用其他的进程去使用CPU。 因而一个进程由三种状态
3)进程并发的实现
程并发的实现在于,硬件中断一个正在运行的进程,把此时进程运行的所有状态保存下来,为此,操作系统维护一张表格,即进程表(process table),每个进程占用一个进程表项(这些表项也称为进程控制块)
该表存放了进程状态的重要信息:程序计数器、堆栈指针、内存分配状况、所有打开文件的状态、帐号和调度信息,以及其他在进程由运行态转为就绪态或阻塞态时,必须保存的信息,从而保证该进程在再次启动时,就像从未被中断过一样。
Python并发编程理论原文链接:http://www.cnblogs.com/linhaifeng/articles/7430066.html
二、进程
1)开启子进程
from multiprocessing import Process import time def task(x): print('%s is running' %x) time.sleep(2) print("%s is done" %x) if __name__ == '__main__': # Process(target=task,kwargs={'x':'任务1'}) # 生成一个进程对象 p=Process(target=task,args=('任务1',)) # 元组必须加逗号,否则是字符串类型 p.start() # 只是给操作系统发送一个开启子进程的信号 print('主')
2)查看进程号(进程ID),pid及ppid
from multiprocessing import Process import time import os def task(): print('子进程的pid:%s,父进程的pid ppid:%s' %(os.getpid(),os.getppid())) time.sleep(1) if __name__ == '__main__': p=Process(target=task,) p.start() print('主:',os.getpid(),os.getppid())
tasklist 查看ID
tasklist | findstr 11244 过滤ID
3)使用自定义类方法来创建子进程
from multiprocessing import Process import time class MyProcess(Process): def __init__(self,name): super().__init__() self.name=name def run(self): # 函数名一定得叫run print('%s is ruuning' %self.name) time.sleep(3) print('%s is done' %self.name) def func(self): print('new func') if __name__ == '__main__': p=MyProcess('egon') p.start() # 调用类里面的 run 方法,即run 方法乃 子进程 print('主') p.func()
4)join 方法。必先执行完子进程,才能执行主进程
from multiprocessing import Process import time def task(x): print('%s is ruuning' %x) time.sleep(3) print('%s is done' %x) if __name__ == '__main__': p=Process(target=task,args=('子进程',)) p.start() # time.sleep(5) p.join() #主进程在等,一直等到子进程p运行完毕后再执行下一行代码 print('主')
多个子进程,重用执行的时间,用时 3.6552090644836426秒。会与后面的线程对比
from multiprocessing import Process import time,os def task(n): print('%s is ruuning' %os.getpid()) time.sleep(n) if __name__ == '__main__': p1=Process(target=task,args=(1,)) p2=Process(target=task,args=(2,)) p3=Process(target=task,args=(3,)) start_time=time.time() p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() stop_time=time.time() print('主',(stop_time - start_time)) # 主 3.6552090644836426
循环添加进程,并循环执行
from multiprocessing import Process import time,os def task(n): print('%s is ruuning' %os.getpid()) time.sleep(n) if __name__ == '__main__': p_l=[] start_time=time.time() for i in range(1,4): p=Process(target=task,args=(i,)) p_l.append(p) p.start() for p in p_l: p.join() stop_time=time.time() print('主',(stop_time - start_time))
5)进程的其他方法,属性
p.name,p.pid # 打印子进程的名字
p.pid # 子进程的pid
p.terminate() # 强行终止子进程
print(p.is_alive()) # 查看子进程是否还活着
from multiprocessing import Process import time,os def task(n): print('%s is ruuning' %os.getpid()) time.sleep(n) if __name__ == '__main__': p=Process(target=task,args=(3,),name='子进程1') p.start() # print(p.name,p.pid) # 打印子进程的名字,查看子进程的pid # p.terminate() # 强行终止子进程 # time.sleep(1) p.join() print(p.is_alive()) # 查看进程是否还活着 print('主')
6)进程之间内存隔离
from multiprocessing import Process import time,os x=100 def task(): global x x=0 if __name__ == '__main__': p=Process(target=task) p.start() # p.join() print('主',x)
7)多进程实现socket并发操作
import socket from multiprocessing import Process def talk(conn): while True: try: data = conn.recv(1024) if not data: break print('客户端数据:%s' % data) conn.send(data.upper()) except ConnectionResetError: break conn.close() def server(ip,port): phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #流式协议指的就是tcp协议 phone.bind((ip,port)) #端口范围0-65535 phone.listen(5) #限制的是请求数,而非链接数 print('服务的启动......') while True: # 连接循环 conn,client_addr=phone.accept() print(client_addr) # 通信循环 # talk(conn) p=Process(target=talk,args=(conn,)) p.start() phone.close() if __name__ == '__main__': server('127.0.0.1',8081)
import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',8081)) while True: msg=input('>>>: ').strip() if not msg:continue phone.send(msg.encode('utf-8')) data=phone.recv(1024) print(data.decode('utf-8')) phone.close()
这种方法不科学,设置过多的进程,会大量消耗资源。并且,收到的并发数量大于进程数量,服务端会崩溃掉。
原文链接:http://www.cnblogs.com/linhaifeng/articles/7428874.html
三、线程
1)线程介绍
1 什么线程 线程就是一条流水线的工作过程,一个进程内至少有一个线程 进程只是一个资源单位 而进程内的线程才执行单位 2 为什么要多线程(进程vs线程) 1、同一进程下的多个线程共享该进程内的数据 2、线程的创建开销要远远小于进程的 3 如何用线程 1、from threading import Thread 2、t=Thread(target=def,args=(xxx,))
2)开启线程的2种方式
第一种,函数方式
from threading import Thread import time,random def piao(name): print('%s is piaoing' %name) time.sleep(random.randint(1,3)) print('%s is piao end' % name) if __name__ == '__main__': t=Thread(target=piao,args=('user',)) t.start() print('主')
第二种,类方式
from threading import Thread import time,random class Mythread(Thread): def run(self): print('%s is piaoing' %self.name) time.sleep(random.randint(1,3)) print('%s is piao end' % self.name) if __name__ == '__main__': t=Mythread() t.start() print('主')
3)线程之间数据共享
from threading import Thread x=100 def task(): global x x=0 if __name__ == '__main__': t=Thread(target=task) t.start() t.join() print('主',x)
4)线程的其他属性方法,如定义线程名,线程的存活状态
from threading import Thread def task(name): print('%s is ruuning' %name) if __name__ == '__main__': t=Thread(target=task,args=('egon',),name='线程1') t.start() print(t.is_alive()) t.setName('线程') print(t.getName()) # print('主')
在线程里查看自己的线程名的方法
from threading import Thread,current_thread def task(): print('%s is ruuning' %current_thread().getName()) if __name__ == '__main__': t=Thread(target=task) t.setName('线程') t.start() print('主')
5)同一个进程下的线程的pid一样,以及执行的效率比进程快近100倍。耗时:3.0161726474761963
from threading import Thread,current_thread import os,time def task(n): print('%s is ruuning,pid:%s' %(current_thread().getName(),os.getpid())) time.sleep(n) if __name__ == '__main__': t1=Thread(target=task,args=(1,)) t2=Thread(target=task,args=(2,)) t3=Thread(target=task,args=(3,)) start=time.time() t1.start() t2.start() t3.start() t1.join() t2.join() t3.join() print('主',os.getpid()) print(time.time()-start)
原文链接http://www.cnblogs.com/linhaifeng/articles/7428877.html