day21&22&23:线程、进程、协程
1、程序工作原理
进程的限制:每一个时刻只能有一个线程来工作。
多进程的优点:同时利用多个cpu,能够同时进行多个操作。缺点:对内存消耗比较高
当进程数多于cpu数量的时候会导致不能被调用,进程不是越多越好,cpu与进程数量相等最好
线程:java和C# 对于一个进程里面的多个线程,cpu都在同一个时刻能使用。py同一时刻只能调用一个。
so:对于型的应用,py效率较java C#低。
多线程优点:共享进程的内存,可以创造并发操作。缺点:抢占资源,
多线程得时候系统在调用的时候需要记录请求上下文的信息,请求上下文的切换 这个过程非常耗时。因此 线程不是越多越好,具体案例具体分析。
在计算机中,执行任务的最小单元就是线程
IO操作不利用CPU,IO密集型操作适合多线程,对于计算密集型适合多进程
GIL:全局解释器锁,PY特有它会在每个进程上加个锁
系统存在进程和线程的目的是为了提高效率
1.1、单进程单线程
1.2、自定义线程:
主进程
主线程
子线程
2、线程锁 threading.RLock和threading.Lock
多线程修改一个数据得时候可能会造成咱数据。建议使用rlock
3、线程时间:threading.Event: 通知
当有进程间的通讯的情况下这个才有应用场景。汽车类比线程,Event.wait()红灯,Event.set()绿灯,Event.clear():使红灯变绿
even是线程间的通讯机制。Event.wait([timeout]):赌赛线程,知道event对象内部标示位被设置为True或超时时间。Event.set():将标识位设为True。Event.clear():标识位设为False。Event.isSet():判断标识位是否为True。
4、queue模块:生产者-消费者模型
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import queue
import threading
# import queue # q = queue.Queue(maxsize=0) # 构造一个先进显出队列,maxsize指定队列长度,为0 时,表示队列长度无限制。
#
# q.join() # 等到队列为空的时候,在执行别的操作
# q.qsize() # 返回队列的大小 (不可靠)
# q.empty() # 当队列为空的时候,返回True 否则返回False (不可靠)
# q.full() # 当队列满的时候,返回True,否则返回False (不可靠)
# q.put(item, block=True, timeout=None) # 将item放入Queue尾部,item必须存在,可以参数block默认为True,表示当队列满时,会等待队列给出可用位置,
# # 为False时为非阻塞,此时如果队列已满,会引发queue.Full 异常。 可选参数timeout,表示 会阻塞设置的时间,过后,
# # 如果队列无法给出放入item的位置,则引发 queue.Full 异常
# q.get(block=True, timeout=None) # 移除并返回队列头部的一个值,可选参数block默认为True,表示获取值的时候,如果队列为空,则阻塞,为False时,不阻塞,
# # 若此时队列为空,则引发 queue.Empty异常。 可选参数timeout,表示会阻塞设置的时候,过后,如果队列为空,则引发Empty异常。
# q.put_nowait(item) # 等效于 put(item,block=False)
# q.get_nowait() # 等效于 get(item,block=False) message = queue.Queue(10) def producer(i):
print("put:",i)
# while True:
message.put(i) def consumer(i):
# while True:
msg = message.get()
print(msg) for i in range(12):
t = threading.Thread(target=producer, args=(i,))
t.start() for i in range(10):
t = threading.Thread(target=consumer, args=(i,))
t.start()
qs = message.qsize()
print("当前消息队列的长度为:%d"%(qs))
print("当前消息队列的长度为:",qs)
queue示例代码
join()方法主线程等待,最多等待时间可以hi设置,eg:t.join(2)
import threading
def f0():
pass
def f1(a1,a2):
time.sleep(10)
f0()
t = threading.Thread(target=f1,args(111,222,)) t.setDaemon(True) #默认false 主线程将等待执行完成后结束,设置为true后主线程将不在等待
t.start()
t = threading.Thread(target=f1,args(111,222,))
t.start()
t = threading.Thread(target=f1,args(111,222,))
t.start()
t = threading.Thread(target=f1,args(111,222,)) t.start()
threading demo
5、进程 :multiprocess是py进程模块
进程之间默认是隔离得,线程的资源默认是共享的
两个进程共享数据需要使用特殊得对象: array:其他语音 或manager.dict()
进程不是,越多越好,建议使用线程池来控制。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from multiprocessing import Pool
import time
def myFun(i):
time.sleep(2)
return i+100 def end_call(arg):
print("end_call",arg) # print(p.map(myFun,range(10)))
if __name__ == "__main__":
p = Pool(5) for i in range(10):
p.apply_async(func=myFun,args=(i,),callback=end_call) print("end")
p.close()
p.join()
porcesspooldemo
#!/usr/bin/env python
# -*- coding:utf-8 -*- from multiprocessing import Pool
import time def f1(a):
time.sleep(1)
print(a)
return 1000
def f2(arg):
print(arg) if __name__ =="__main__":
pool = Pool(5) for i in range(50):
pool.apply_async(func=f1, args=(i,),callback=f2)
# pool.apply(func=f1, args=(i,))
print('<<=================>>')
pool.close()
pool.join()
processpooldemo2
6、线程池py没有提供,我们需要自己编写
简单线程池示例:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import queue
import threading
import time class ThreadPool(object): def __init__(self, max_num=20):
self.queue = queue.Queue(max_num)
for i in range(max_num):
self.queue.put(threading.Thread) def get_thread(self):
return self.queue.get() def add_thread(self):
self.queue.put(threading.Thread) def func(pool,a1):
time.sleep(2)
print(a1)
pool.add_thread() p = ThreadPool(10) for i in range(100):
#获得类
thread = p.get_thread()
#对象 = 类()
#
t = thread(target=func,args=(p,i,))
t.start()
"""
pool = ThreadPool(10) def func(arg, p):
print arg
import time
time.sleep(2)
p.add_thread() for i in xrange(30):
thread = pool.get_thread()
t = thread(target=func, args=(i, pool))
t.start()
""" # p = ThreadPool()
# ret = p.get_thread()
#
# t = ret(target=func,)
# t.start()
复杂的线城池示例:
#!/usr/bin/env python
# -*- coding:utf-8 -*- import queue
import threading
import contextlib
import time StopEvent = object() class ThreadPool(object): def __init__(self, max_num, max_task_num = None):
if max_task_num:
self.q = queue.Queue(max_task_num)
else:
self.q = queue.Queue()
# 多大容量
self.max_num = max_num
self.cancel = False
self.terminal = False
# 真实创建的线程列表
self.generate_list = []
# 空闲线程数量
self.free_list = [] def run(self, func, args, callback=None):
"""
线程池执行一个任务
:param func: 任务函数
:param args: 任务函数所需参数
:param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数)
:return: 如果线程池已经终止,则返回True否则None
"""
if self.cancel:
return
if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
self.generate_thread()
w = (func, args, callback,)
self.q.put(w) def generate_thread(self):
"""
创建一个线程
"""
t = threading.Thread(target=self.call)
t.start() def call(self):
"""
循环去获取任务函数并执行任务函数
"""
# 获取当前进程
current_thread = threading.currentThread()
self.generate_list.append(current_thread) # 取任务
event = self.q.get()
while event != StopEvent:
# 是元组=》是任务
# 解开任务包
# 执行任务 func, arguments, callback = event
try:
result = func(*arguments)
success = True
except Exception as e:
success = False
result = None if callback is not None:
try:
callback(success, result)
except Exception as e:
pass with self.worker_state(self.free_list, current_thread):
if self.terminal:
event = StopEvent
else:
event = self.q.get()
else: # 不是元组,不是任务
# 标记:我空闲了
# 执行后线程死掉
self.generate_list.remove(current_thread) def close(self):
"""
执行完所有的任务后,所有线程停止
"""
self.cancel = True
full_size = len(self.generate_list)
while full_size:
self.q.put(StopEvent)
full_size -= 1 def terminate(self):
"""
无论是否还有任务,终止线程
"""
self.terminal = True while self.generate_list:
self.q.put(StopEvent) self.q.empty() @contextlib.contextmanager
def worker_state(self, state_list, worker_thread):
"""
用于记录线程中正在等待的线程数
"""
state_list.append(worker_thread)
try:
yield
finally:
state_list.remove(worker_thread) # How to use pool = ThreadPool(5) def callback(status, result):
# status, execute action status
# result, execute action return value
pass def action(i):
print(i) for i in range(30):
#将任务放在队列
#着手开始处理任务
#创建线程(有空闲线程则不创建;不高于线程池的限制;根据任务个数判断) =》线程去队列中去任务
ret = pool.run(action, (i,), callback) time.sleep(5)
print(len(pool.generate_list), len(pool.free_list))
print(len(pool.generate_list), len(pool.free_list))
# pool.close()
# pool.terminate()
7、上下文管理:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import queue
import contextlib
"""
q = queue.Queue()
li = [] # li.append(1)
# q.get()
# li.remove(1) @contextlib.contextmanager
def worker_stater(xxx,val):
xxx.append(val)
try:
yield 123
finally:
xxx.remove(val) q.put("john")
with worker_stater(li,1) as f:
print('before',li)
print(f)
q.get()
pass
pass print('after',li)
""" @contextlib.contextmanager
def myopen(file_path,mode):
f = open(file_path,mode,encoding='utf-8')
try:
yield f
finally:
f.close() with myopen('index.html','r') as file_obj:
print(file_obj.readline())
demo
8、协程:
协程主要应用在IO密集型场景,由程序来控制,也叫微线程,高性能通常与协程挂钩
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import gevent def foo():
print('Running in foo')
gevent.sleep(0) #切换协程
print('Explicit context switch to foo agein')
def bar():
print('Running in bar')
gevent.sleep(0) #切换协程
print('Explicit context switch back to bar agein') gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
demo1
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from gevent import monkey;monkey.patch_all()
import gevent
import requests def f(url):
print('GET:%s' % url)
resp = requests.get(url)
data = resp.text
print(url,len(data)) gevent.joinall([
gevent.spawn(f,'http://www.python.org/'),
gevent.spawn(f,'https://www.yahoo.com/'),
gevent.spawn(f,'https://github.com/'),
])
demo2
#!/usr/bin/env python
# -*- coding:utf-8 -*- from greenlet import greenlet def test1():
print(12)
gr2.switch()
print(34)
gr2.switch() def test2():
print(56)
gr1.switch()
print(78)
gr1.switch() gr1 = greenlet(test1)
gr2 = greenlet(test2) gr1.switch()
demo3
end
day21&22&23:线程、进程、协程的更多相关文章
- 学到了林海峰,武沛齐讲的Day34 完 线程 进程 协程 很重要
线程 进程 协程 很重要 ...儿子满月回家办酒,学的有点慢,坚持
- 文成小盆友python-num11-(1) 线程 进程 协程
本节主要内容 线程补充 进程 协程 一.线程补充 1.两种使用方法 这里主要涉及两种使用方法,一种为直接使用,一种为定义自己的类然后继承使用如下: 直接使用如下: import threading d ...
- Python学习笔记整理总结【网络编程】【线程/进程/协程/IO多路模型/select/poll/epoll/selector】
一.socket(单链接) 1.socket:应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socke ...
- 线程&进程&协程
线程 线程是应用程序中工作的最小单元,它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务.Threading用 ...
- 15.python并发编程(线程--进程--协程)
一.进程:1.定义:进程最小的资源单位,本质就是一个程序在一个数据集上的一次动态执行(运行)的过程2.组成:进程一般由程序,数据集,进程控制三部分组成:(1)程序:用来描述进程要完成哪些功能以及如何完 ...
- python之并发编程(线程\进程\协程)
一.进程和线程 1.进程 假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源.是 ...
- python_21_线程+进程+协程
python_线程_进程_协程 什么是线程? -- os能够进行运算调度的最小单位,被包含在进程之中,是一串指令的集合 -- 每个线程都是独立的,可以访问同一进程下所有的资源 什么是进程? -- 每个 ...
- python 线程 进程 协程 学习
转载自大神博客:http://www.cnblogs.com/aylin/p/5601969.html 仅供学习使用···· python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和 ...
- python中线程 进程 协程
多线程:#线程的并发是利用cpu上下文的切换(是并发,不是并行)#多线程执行的顺序是无序的#多线程共享全局变量#线程是继承在进程里的,没有进程就没有线程#GIL全局解释器锁#只要在进行耗时的IO操作的 ...
- Python—进程、线程、协程
一.线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 方法: ...
随机推荐
- html标签补充
<body>内常用标签 1.<div>和<span> <div></div> : <div>只是一个块级元素,并无实际的意义.主 ...
- websocket的加密和解密
补充个小知识点:按位与运算 按位与运算是同位都为1才为1,有一个不为1就是0 websocket_hand import socket, base64, hashlib import websocke ...
- 安装mysql-installer-community
1.在官网上下载mysql-installer-community-5.6.25.0 2.选择MySQL Installer 3.选择Windows (x86, 32-bit), MSI Instal ...
- 树莓派-(一)开箱到点亮一些坑(无屏、无wlan、无直连键鼠)
0x00.前期准备: 材料: 树莓派3b+ 板子 * 1,适配电源 * 1,网线 * 2,sd卡16G * 1,读卡器 * 1 安装时注意,3b+三个散热片贴好.小风扇接线要接对 工具: 0x01. ...
- Winform 读取 指定\另一个\其他\任意 配置文件
ExeConfigurationFileMap map = new ExeConfigurationFileMap(); map.ExeConfigFilename = @&qu ...
- javascript设计模式之中介者模式
/* * 小游戏演示中介者模式 * Home 按键 1 * Guest 按键 0 * 半分钟内看谁按下的次数多 * * 参与的对象: * 玩家 * 计分板 * 中介者 * * 中介者模式使对象之间松耦 ...
- 559. N 叉树的最大深度
给定一个 N 叉树,找到其最大深度. 最大深度是指从根节点到最远叶子节点的最长路径上的节点总数. 例如,给定一个 3叉树 : 我们应返回其最大深度,3. 说明: 树的深度不会超过 1000.树的节点总 ...
- LeetCode Merge Two Sorted Lists 归并排序
题意: 将两个有序的链表归并为一个有序的链表. 思路: 设合并后的链表为head,现每次要往head中加入一个元素,该元素要么属于L1,要么属于L2,可想而知,此元素只能是L1或者L2的首个元素, ...
- 详细讲解:通过phpstudy 设置站点域名、站点域名管理
我们在本地编程的时候,会遇到路径特别长的情况,这样子我们在url中的输入就会变得不方便而且容易报错,那么在phpstudy这个环境中,有一个很好的功能,就是“站点域名管理”,他能让我们的url网址大大 ...
- ABAP Netweaver, Hybris Commerce和SAP 云平台的登录认证
ABAP Netweaver 在事务码SICF里选择一个服务,在明细页面对Procedure字段点击F1,查看Logon Procedure的帮助文档. 通过这个链接打开对应的帮助文档,可以看到下列七 ...