RUN__IT # 多任务---线程---进程---协程

线程

每个线程的执行时间不确定,线程是操作系统调度执行的最小单位.

线程的创建步骤

# 导入threading模块
import threading
# 创建一个线程对象
t1 = threading.Thread(target=func_name, args=(num,),name=”子线程名字”)
# 创建一个线程并启动
t1.start()
# 等待子线程执行完毕之后再继续向下执行主线程
t1.join()

备注:主线程会等待子线程结束之后才会结束,主线程一死,子线程也会死。线程的调度是随机的,并没有先后顺序

互斥锁的运用

由于多线程之间共享全局变量就会导致出现资源竞争的问题,为了避免这种竞争出现,利用互斥锁可以实现线程同步。

# 创建锁
Mutex = threading.Lock()

# 加锁
Mutex.acquire()

# 释放锁
Mutex.release()

在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁,尽管死锁很少发生,但一旦发生就会造成应用的停止响应.
超时时间解锁:
# 加锁时加超时时间
Mutex.acquire(timeout=1)

threading模块的对象

对象 描述
Thread 表示一个执行线程的对象
Lock 锁原语对象
RLock 可重入锁对象,使单一线程可以(再次)获得已持有的锁(递归锁)
…待添加…

Thread类

Thread对象方法 描述
init(group=None,tatget=None,name=None,args=(),kwargs={},verbose=None,daemon=None) 实例化一个线程对象,需要有一个可调用的target,以及其参数args或kwargs
star() 开始执行线程
run 定义线程功能的方法(通常在子类中被应用开发者重写)
join(timeout=None) 直至启动的线程终止前一直挂起,除非给了超时,否则一直阻塞

进程

进程的创建步骤

# 导入进程模块
import multiprocessing
# 创建一个进程的实例对象
p = multiprocessing.Process(target=fun_name,args=(元组),kwargs={字典})
# 创建并启动进程
p.start()
​
p.join()  可以阻塞主进程,等待子进程的结束
​
# 获取进程的pid
os.getpid()
# 获取进程的父进程的pid
os.getppid()
​
**进程中,主进程的父进程pid是系统产生的,子进程的父进程pid是主进程的pid,
主进程死掉,子进程不会死,子进程会有新的父进程,(这个进程的名字好像是upstart)如果继续kill掉这个进程,将锁屏。

通过Queue实现进程间通信

# 创建一个队列
q = multiprocessing.Queue(5)  # 5代表队列可以接受的容量
# 向队列添加数据
q.put(data)
# 从队列中获取数据
q.get()
# 判断队列是否为空,为空返回True
q.empty()
# 判断队列中是否已满
q.full()
​
**注意:如果是通过进程池创建的进程,那么队列的使用要用 multiprocessing.Manager().Queue()的方式,否则会报错。**

进程池Pool

# 导入进程池模块
from multiprocessing import Pool
# 定义进程池,最大进程数
po = Pool(3)
# 通过进程池调用目标 apply_async 非阻塞,不会等待子进程结束,apply 阻塞,会等待子进程结束才结束
po.apply_async(要调用的目标,(传递给目标的参数元组,))
# 关闭进程池
po.close()
# 等待进程池执行完毕
po.join()

协程

协程,又称微线程,纤程。利用线程在等待某个资源的期间执行其他函数,切换资源消耗非常小,协程效率相当快。

进程、线程、协程的区别

1. 进程是资源分配的单位
2. 线程是操作系统调度的单位
3. 进程切换需要的资源很最大,效率很低
4. 线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)
5. 协程切换任务资源很小,效率高
6. 多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发
7. 协程依赖于线程,线程依赖于进程,进程一死线程必挂,线程一死协程必死。

gevent

import gevent
def f(n):
    for i in range(n):
        print(gevent.getcurrent(), i)
        #用来模拟一个耗时操作,注意不是time模块中的sleep
        gevent.sleep(1)
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()

并发下载器

from gevent import monkey
import gevent
import urllib.request

# 有耗时操作是需要,打补丁
monkey.patch_all()

def my_download(name,url):
	# 请求
	resp = urllib.request.urlopen(url)
	data = respl.read()
	# 保存数据
	with open(name,"wb") as f:
		f.write(data)

def main():
	gevent.joinall([ gevent.spawn(my_download, "1.jpg", "https://img02.sogoucdn.com/app/a/100520024/8eb2dc17fb6a6a87ae12aeb319dfc239")) ])


if __name__ == "__main__":
	main()


猜你喜欢

转载自blog.csdn.net/RUN__IT/article/details/89162809
今日推荐