python之并发编程初级篇8
一、进程理论
1)进程介绍
- 、什么是进程
- 一个正在进行的过程,或者说是一个程序的运行过程
- 其实进程是对正在运行的程序的一种抽象/概括的说法
- 进程的概念起源操作系统,进程是操作最核心的概念之一
- 操作系统其他所有的概念都是围绕进程展开的
- 、多道路技术
- 产生背景:针对单核,实现并发
- ps:
- 现在的主机一般是多核,那么每个核都会利用多道技术
- 有4个cpu,运行于cpu1的某个程序遇到io阻塞,会等到io结束再重新调度,会被调度到4个
- cpu中的任意一个,具体由操作系统调度算法决定。
- .空间上的复用:如内存中同时有多道程序
- .时间上的复用:复用一个cpu的时间片
- 强调:遇到io切,占用cpu时间过长也切,核心在于切之前将进程的状态保存下来,这样
- 才能保证下次切换回来时,能基于上次切走的位置继续运行
- 、并发vs并行
- 并发(单核就可以实现并发)
- 多个任务看起来是同时运行的就是并发
- 并发的实现=切换+保存状态
- 并行(只有多核才能实现并行)
- 真正意义上的同时运行
2)进程状态
- tail -f access.log |grep ''
- 执行程序tail,开启一个子进程,执行程序grep,开启另外一个子进程,两个进程之间基于管道'|'通讯,将tail的结果作为grep的输入。
- 进程grep在等待输入(即I/O)时的状态称为阻塞,此时grep命令都无法运行
- 其实在两种情况下会导致一个进程在逻辑上不能运行,
- . 进程挂起是自身原因,遇到I/O阻塞,便要让出CPU让其他进程去执行,这样保证CPU一直在工作
- . 与进程无关,是操作系统层面,可能会因为一个进程占用时间过多,或者优先级等原因,而调用其他的进程去使用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()
- 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()
- 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()
- 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()
- print('%s is done' %x)
- if __name__ == '__main__':
- p=Process(target=task,args=('子进程',))
- p.start()
- # time.sleep()
- 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=(,))
- p2=Process(target=task,args=(,))
- p3=Process(target=task,args=(,))
- 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(,):
- 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=(,),name='子进程1')
- p.start()
- # print(p.name,p.pid) # 打印子进程的名字,查看子进程的pid
- # p.terminate() # 强行终止子进程
- # time.sleep()
- p.join()
- print(p.is_alive()) # 查看进程是否还活着
- print('主')
示例
6)进程之间内存隔离
- from multiprocessing import Process
- import time,os
- x=
- def task():
- global x
- x=
- 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()
- 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-
- phone.listen() #限制的是请求数,而非链接数
- 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',)
服务端
- import socket
- phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- phone.connect(('127.0.0.1',))
- while True:
- msg=input('>>>: ').strip()
- if not msg:continue
- phone.send(msg.encode('utf-8'))
- data=phone.recv()
- print(data.decode('utf-8'))
- phone.close()
客户端
这种方法不科学,设置过多的进程,会大量消耗资源。并且,收到的并发数量大于进程数量,服务端会崩溃掉。
原文链接:http://www.cnblogs.com/linhaifeng/articles/7428874.html
三、线程
1)线程介绍
- 什么线程
- 线程就是一条流水线的工作过程,一个进程内至少有一个线程
- 进程只是一个资源单位
- 而进程内的线程才执行单位
- 为什么要多线程(进程vs线程)
- 、同一进程下的多个线程共享该进程内的数据
- 、线程的创建开销要远远小于进程的
- 如何用线程
- 、from threading import Thread
- 、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(,))
- 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(,))
- print('%s is piao end' % self.name)
- if __name__ == '__main__':
- t=Mythread()
- t.start()
- print('主')
3)线程之间数据共享
- from threading import Thread
- x=
- def task():
- global x
- x=
- 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=(,))
- t2=Thread(target=task,args=(,))
- t3=Thread(target=task,args=(,))
- 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
python之并发编程初级篇8的更多相关文章
- python之并发编程进阶篇9
一.守护进程和守护线程 1)守护进程的概念 什么是守护进程: 守护: 在主进程代码结束情况下,就立即死掉 守护进程本质就是一个子进程,该子进程守护着主进程 为何要用守护进程 守护进程本质就是一个子进程 ...
- Python并发编程理论篇
Python并发编程理论篇 前言 其实关于Python的并发编程是比较难写的一章,因为涉及到的知识很复杂并且理论偏多,所以在这里我尽量的用一些非常简明的语言来尽可能的将它描述清楚,在学习之前首先要记住 ...
- Python 正则表达式入门(初级篇)
Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写. 转载请写明出处 引子 首先说 正则表达式是什么? 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达 ...
- 转载 Python 正则表达式入门(初级篇)
Python 正则表达式入门(初级篇) 本文主要为没有使用正则表达式经验的新手入门所写.转载请写明出处 引子 首先说 正则表达式是什么? 正则表达式,又称正规表示式.正规表示法.正规表达式.规则表达式 ...
- HTML5 Canvas(画布)实战编程初级篇:基本介绍和基础画布元素
欢迎大家阅读HTML5 Canvas(画布)实战编程初级篇系列,在这个系列中,我们将介绍最简单的HTML5画布编程.包括: 画布元素 绘制直线 绘制曲线 绘制路径 绘制图形 绘制颜色,渐变和图案 绘制 ...
- Python 3 并发编程多进程之进程同步(锁)
Python 3 并发编程多进程之进程同步(锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,竞争带来的结果就是错乱,如何控制,就是加锁处理. 1. ...
- Python 3 并发编程多进程之守护进程
Python 3 并发编程多进程之守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemo ...
- Python 3 并发编程多进程之队列(推荐使用)
Python 3 并发编程多进程之队列(推荐使用) 进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的. 可以往 ...
- python - 面向对象编程(初级篇)
写了这么多python 代码,也常用的类和对象,这里准备系统的对python的面向对象编程做以下介绍. 面向对象编程(Object Oriented Programming,OOP,面向对象程序设计) ...
随机推荐
- cnpm安装
npm install -g cnpm --registry=https://registry.npm.taobao.org 如果安装失败,可以使用 npm cache clean 清理缓存,然后再重 ...
- 我和struts2 的第一天
文字解析 1.获取正文请求 2.根据请求做出判断 3.执行具体的方法代码 4.跳转页面,展示给用户 Strut 是Apache发行的MVC框架 他只是表现层的框架 Strut1 是2005年流行的框架 ...
- 两种方法修改pyhton爬虫的报头
方法一: import urlib.request url = "" headers=("User-Agent","") opener = ...
- Anaconda常用命令大全
使用conda 首先我们将要确认你已经安装好了conda 配置环境 下一步我们将通过创建几个环境来展示conda的环境管理功能.使你更加轻松的了解关于环境的一切.我们将学习如何确认你在哪个环境中,以及 ...
- 25 【python入门指南】如何编写测试代码
python如何编写测试代码 python内置了unittest,使得写应用层的单元测试变得超乎寻常的简单. 1,执行单个测试函数 #!/bin/python import unittest clas ...
- 【Linux 进程】fork函数详解
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同, ...
- Java遍历文件夹下的所以文件
利用Java递归遍历文件夹下的所以文件,然后对文件进行其他的操作.如:对文件进行重命名,对某一类文件进行重编码.可以对某一工程下的全部.java文件进行转码成utf-8等 代码如下,这里只对文件进行重 ...
- BadgeView 圆形数字提醒 购物车常用
实际上BadgeView这个类就是继承TextView的.很多TextView中设置字体的方法都适用于BadgeView. 1. setTargetView(View) --> 设置哪个控件显示 ...
- 错误:“Cannot load JDBC driver class 'com.mysql.jdbc.Driver”的解决方法
“Cannot load JDBC driver class 'com.mysql.jdbc.Driver ” 表示没有JDBC连接MySql的驱动包,因此需要手动添加驱动包到WEB-INF目录下的l ...
- 8P - 钱币兑换问题
在一个国家仅有1分,2分,3分硬币,将钱N兑换成硬币有很多种兑法.请你编程序计算出共有多少种兑法. Input 每行只有一个正整数N,N小于32768. Output 对应每个输入,输出兑换方法数. ...