多任务

    什么是任务
一个电脑运行这的软件
什么是多任务
电脑同时运行着的多个软件
多任务原理
时间片的轮转
并行与并发
并发:假的多任务,多个任务共用一个核
并行:正的多任务,一个核处理一个程序
生理过程(从生到死)
创建 -> 就绪 -> 运行 -> 阻塞 -> 死亡
线程和进程的创建一定要在主函数中,且主任务和子任务一起往下执行,遇到join()方法,主任务会等子任务执行完在结束

线程

        特点
查看正在运行的线程列表
threading.enumerate()
只要程序已启动,Python解释器就会自动创建一个主线程
主线程等待其他线程结束后在结束
线程target指向的函数执行完毕,线程就结束了
子线程是调用start()之后开启的
多个线程共享全局变量 创建
通过继承的方式创建线程
特点:写法复杂,使用简单,可以使用对象的特性(封装、继承、多态)业务逻辑比较复杂时使用
方式一
import threading
p = threading.Thread(target=函数名,args=(1,))
          p.setDaemon(True) # 开启守护线程
p.start()
p.join() 方式二
          # 线程类
import threading
class MyThread(threading.Thread):
def run():
print('子线程要做的事')
t = MyThread()
          t.setDaemon(True)
t.start()
t.join()
互斥锁
-->科学家吃面(筷子和碗)
1.什么是资源竞争?
多个线程争抢做同一件事
2.资源竞争会带来什么问题?
多线程共享同一个资源的时候,当操作这个资源(变量)足够多的次数时,可能会出现问题 eg:1000000次的累加
3.如何解决资源竞争的问题?
互斥锁
4.什么是互斥锁?
确保了某段关键代码只能由一个线程从头到尾完整地执行
5.如何使用互斥锁?
1.创建锁对象
mutex = threading.Lock()
2.获取锁
mutex.acquire()
3.释放锁
mutex.release()
6.原则:
存在资源竞争的代码,加锁的代码越少越少
7.死锁
什么是死锁?
线程1等待线程2释放锁,线程2等待线程1释放锁
如何解决死锁?
1.设计写代码的时候就避免
2.设置超时时间
3.银行家算法

队列

from queue import Queue

q = Queue(maxsize=100)
item = {}
q.put_nowait(item) #不等待直接放,队列满的时候会报错
q.put(item) #放入数据,队列满的时候回等待
q.get_nowait() #不等待直接取,队列空的时候会报错
q.get() #取出数据,队列为空的时候会等待
q.qsize() #获取队列中现存数据的个数
q.join() #队列中维持了一个计数,计数不为0时候让主线程阻塞等待,队列计数为0的时候才会继续往后执行
q.task_done()
# put的时候计数+1,get不会-1,get需要和task_done 一起使用才会-1

进程

     1.程序:
就是程序员写的代码,没有运行起来的代码
2.进程
运行起来的程序,代码+计算机资源,进程是实现多任务的第二种方式
3.程序运行起来之后,Python解释器会给程序创建一个进程,叫做主进程 特点
1.查看进程
windows: 任务管理器
linux:ps -aux
杀死进程 kill -9 PID
top htop 相当于windows中的任务管理器
2.进程的写实拷贝
写(修改)的时候拷贝一份
进程不共享全局变量
通过args给进程传递数据
3.获取进程id和父进程的id
os.getpid()
os.getppid()
4.主进程等待子进程结束后再结束(主进程替子进程收尸),进程的运行顺便不确定 创建
方式一
import multiprocessing
p = multiprocessing.Process(target=函数名,args=(1,))
          p.daemon = True # 开启守护进程
p.start()
p.join()
方式二
import multiprocessing
class MyProcess(multiprocessing.Process):
def run():
print("子进程要做的事情")
p = MyProcess()
          p.daemon = True # 开启守护进程
p.start()
p.join()
进程间通信(传递数据)
默认情况下,进程之间不能互相访问数据
队列(Queue)
常用的方法
get()/put()/full()
每个进程都可以往这个队列中写数据,都可以从这个队列中读取数据
编码步骤:
创建队列对象
给队列中放数据
从队列中取数据
进程池(Pool) 什么是进程池?
一次性在进程池中创建多个进程
进程的作用?
减少了销毁线程的次数,从而提高效率
如何使用进程池?
创建进程池对象,调用方法完成任务 from multiprocessing import Pool
import os, time, random
def worker(msg):
t_start = time.time()
print("%s开始执行,进程号为%d" % (msg, os.getpid()))
# random.random()随机生成0~1之间的浮点数
time.sleep(random.random() * 2)
t_stop = time.time()
print(msg, "执行完毕,耗时%0.2f" % (t_stop - t_start)) def main():
po = Pool(3) # 定义一个进程池,最大进程数3
for i in range(0, 10):
# Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
# 每次循环将会用空闲出来的子进程去调用目标
po.apply_async(worker, (i,)) print("----start----")
po.close() # 关闭进程池,关闭后po不再接收新的请求
time.sleep(1)
# po.join() # 等待po中所有子进程执行完成,必须放在close语句之后
print("-----end-----")        # 进程一定要放在入口函数中执行,否则会抛出异常
if __name__ == '__main__':
main()

协程

        什么是可迭代对象
一个普通的对象实现了iter内置函数
什么是迭代器
一个普通的对象实现了iter和next内置函数
迭代器的特点
保存的是生成数据的方式,而不直接存储数据,好处:节省系统空间
什么是生成器
它是一个特殊的迭代器
yield
一个普通的函数里面写了yield的话,他就是一个生成器模板,执行函数遇到yield会阻塞,调用next()或者send()会解阻塞,end()可以用来传递参数
eg:
def func(all_num):
a, b = 0, 1
count_num = 0
while True:
if count_num < all_num:
result = yield a # 如果一个函数中有yield,则说明这是特殊函数,叫生成器的模板
print(">>>>ret>>>>", result)
a, b = b, a + b
count_num += 1
else:
raise StopIteration f = func(10)
ret = next(f)
print(ret)
ret = f.send("hahaha") # 将这个结果传递给 result = yield a 让result来保存"hahaha"
ret1 = next(f)
print(ret1) # 结果为None传递一次send后,后面的数据都需要send来传输,否则结果为None
ret2 = f.send("ok") 利用yield做协程
写多个函数,每个函数中都写yield,函数执行时遇到yield就会阻塞,然后交替着调用不同任务的next()方法,这样就用协程实现了多任务
原理:
利用线程的空闲时间去执行其他的任务
特点:
协程依赖于线程,线程依赖进程,从系统开销讲,进程>线程>协程 创建协程
yield next() send() import gevent
import time
from gevent import monkey monkey.patch_all() def func1(num):
for i in range(num):
print(gevent.getcurrent(), i)
time.sleep(0.5) def func2(num):
for i in range(num):
print(gevent.getcurrent(), i)
time.sleep(0.5) def func3(num):
for i in range(num):
print(gevent.getcurrent(), i)
time.sleep(0.5) def func4(num):
for i in range(num):
print(gevent.getcurrent(), i)
time.sleep(0.5) def func5(num):
for i in range(num):
print(gevent.getcurrent(), i)
time.sleep(0.5)
def main():
gevent.joinall([gevent.spawn(func1, 10),
gevent.spawn(func2, 10),
gevent.spawn(func3, 10),
gevent.spawn(func4, 10),
gevent.spawn(func5, 10)
]) if __name__ == "__main__":
main()

python中的多任务的更多相关文章

  1. python中的多任务--线程

    什么是多任务? 简单地说,就是操作系统可以同时运行多个任务. 实现多任务有多种方式,线程.进程.协程. 多任务的概念:并行和并发 并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法, 实 ...

  2. 深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!

    本文参考:http://www.dabeaz.com/coroutines/   作者:David Beazley 缘起: 本人最近在学习python的协程.偶然发现了David Beazley的co ...

  3. python中的协程及实现

    1.协程的概念: 协程是一种用户态的轻量级线程.协程拥有自己的寄存器上下文和栈. 协程调度切换时,将寄存器上下文和栈保存到其他地方,在切换回来的时候,恢复先前保存的寄存器上下文和栈. 因此,协程能保留 ...

  4. Python中使用多进程来实现并行处理的方法小结

    进程和线程是计算机软件领域里很重要的概念,进程和线程有区别,也有着密切的联系,先来辨析一下这两个概念: 1.定义 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和 ...

  5. Python中的鸡肋多线程

    作者:DarrenChan陈驰链接:https://www.zhihu.com/question/23474039/answer/269526476来源:知乎著作权归作者所有.商业转载请联系作者获得授 ...

  6. python中的多进程与多线程(二)

    1.使用多线程可以有效利用CPU资源,线程享有相同的地址空间和内存,这些线程如果同时读写变量,导致互相干扰,就会产生并发问题,为了避免并发问题,绝不能让多个线程读取或写入相同的变量,因此python中 ...

  7. python中的协程:greenlet和gevent

    python中的协程:greenlet和gevent 协程是一中多任务实现方式,它不需要多个进程或线程就可以实现多任务. 1.通过yield实现协程: 代码: import time def A(): ...

  8. 聊聊Python中的生成器和迭代器

    Python中有两个重要的概念,生成器和迭代器,这里详细记录一下. 1. 生成器 什么是生成器呢? 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包 ...

  9. 聊聊Python中的多进程和多线程

    今天,想谈一下Python中的进程和线程. 最近在学习Django的时候,涉及到了多进程和多线程的知识点,所以想着一下把Python中的这块知识进行总结,所以系统地学习了一遍,将知识梳理如下. 1. ...

随机推荐

  1. 进程与线程(3)- python实现多线程

    参考链接: https://www.jianshu.com/p/415976668b97?utm_campaign=maleskine&utm_content=note&utm_med ...

  2. 洛谷p2234/BZOJ1588 [HNOI2002]营业额统计

    题目链接: 洛谷 BZOJ 分析: 好像没有什么好说的就是一个平衡树的板子--唯一要注意的就是这里要找的并不是严格的前驱和后继,因为如果找到之前某一天的营业额和它相等那么差就是0,所以我们仍然在结构体 ...

  3. Problem E: 穷游中国在统题 优先队列 + 模拟

    http://www.gdutcode.sinaapp.com/problem.php?cid=1049&pid=4 Problem E: 穷游中国在统题 Description Travel ...

  4. mysql数据误删除(drop)的恢复. (ext3grep, extundelete)

    drop table tbl_name 物理删除.没有备份,没有二进制日志 在系统删除文件并非在存储中抹去数据,而仅仅是标识对应的block块可以被重新的分配使用.所以数据的恢复还是有希望的.但是那些 ...

  5. springboot 配置Ehcache

    Ehcache的基本配置说明我就不说了.小编记录一下在springboot中使用Ehcache的使用方法. 第一步:在classpath下引入配置文件ehcache.xml 代码如下: <ehc ...

  6. android开发学习 ------- RecyclerView多类型实例

    实现RecyclerView多类型的实例:效果如下图所示 public class CarFragment extends Fragment{ private View view; private R ...

  7. oracle PL、SQL(概念)

    一.PL/SQL简介. Oracle PL/SQL语言(Procedural Language/SQL)是结合了结构化查询和Oracle自身过程控制为一体的强大语言,PL/SQL不但支持更多的数据类型 ...

  8. SEO & HTML语义化

    SEO SEO的概念:搜索引擎优化,常见的搜索引擎有百度.谷歌等.优化的话,就是通过我们的处理,使得我们的网站在搜索引擎下有一个理想的结果. SEO的目的:当用户在搜索引擎上搜索关键词的时候,看到我们 ...

  9. 关于<meta NAME="keywords" CONTENT="">

    昨天终于以实习身份入职一家小创业公司,今天让我多看看别人的网页怎么写的,发现了一个以前都没关注过的东西. <meta name="keywords" content=&quo ...

  10. UVA 11971 Polygon 多边形(连续概率)

    题意: 一根长度为n的木条,随机选k个位置将其切成k+1段,问这k+1段能组成k+1条边的多边形的概率? 思路: 数学题.要求的是概率,明显与n无关. 将木条围成一个圆后再开切k+1刀,得到k+1段. ...