线程
代码实现
直接使用线程模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import threading
def sing(): print("我在唱歌")
if __name__ == "__main__": t=threading.Thread(target=sing)
t.start() threading.enumerate() len(threading.enumerate())
|
继承线程类
1 2 3 4 5 6 7 8 9 10 11 12 13
| import threading import time
class MyThread(threading.Thread): def run(self): for i in range(3): time.sleep(1) print(i)
if __name__ == "__main__": t=MyThread() t.start()
|
共享全局变量
- 当只修改全局变量的值不需在函数中使用 global声明
- 修改了全局变量指向的内容要在函数中使用global声明
- 用来传递的参数也共享
锁
1 2 3 4 5 6 7 8
| mutex=threading.Lock()
mutex.acquire()
mutex.release()
|
进程
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import multiprocessing
def sing1(): print("菊花台")
def sing2(): print("化蝶")
def main(): p1=multiprocessing.Process(target=sing1) p2=multiprocessing.Process(target=sing2) p1.start() p2.start() if __name__ == "__main__": main()
|
队列实现进程间通信
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import multiprocessing
def down_from_web(q): data=[11,22,33,44]
for temp in data: q.put(temp)
def analysis_data(q): watting_analysis_data=list() while 1: data=q.get() watting_analysis_data.append(data)
if q.empty(): break print(watting_analysis_data)
if __name__ == "__main__": q=multiprocessing.Queue(4)
p1=multiprocessing.Process(target=down_from_web,args=(q,)) p2=multiprocessing.Process(target=analysis_data,args=(q,)) p1.start() p2.start()
|
进程池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import multiprocessing
def woker(msg): print(msg)
po=multiprocessing.Pool(3)
for i in range(0,10): po.apply_async(woker,(i))
po.close()
po.join()
|
协程
一条线程时间片轮转实现多任务
在一条线程执行某函数需耗时切换另一个函数
迭代器
迭代器:存储的是生成数据的方式,占用很小的空间
例如:python2版本的range直接生成一个列表,python3版本的range存放生成数据的方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| from collections.abc import Iterable from collections.abc import Iterator
class Classmate(object): def __init__(self): self.names=list()
def add(self,name): self.names.append(name)
def __iter__(self): return ClassIterator(self)
class ClassIterator(object): def __init__(self,obj): self.obj=obj self.current_num=0
def __iter__(self): pass
def __next__(self): if self.current_num<len(self.obj.names): ret=self.obj.names[self.current_num] self.current_num+=1 return ret else: raise StopIteration
|
迭代器本身就可以迭代
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Classmate(object): def __init__(self): self.names=list() self.current_num=0
def add(self,name): self.names.append(name)
def __iter__(self): return self def __next__(self): if self.current_num<len(self.obj.names): ret=self.obj.names[self.current_num] self.current_num+=1 return ret else: raise StopIteration
|
生成器
生成器是一种特殊的迭代器(没有iter和next方法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| def creat_num(all_num): a,b=0,1 current_num=0 while current_num<all_num: yield a a,b=b,a+b current_num+=1
obj=creat_num(10)
for num in obj: print(num)
|
注意:
- 可以使用next()调用生成器的next方法
- 生成多个生成器互不干扰
- 生成器对象有send方法可以传参数一般开始先用next(),如果第一个运行可以传None作为参数
1 2 3 4 5 6 7 8 9 10
| 用next取值时要抛异常 while True: try: ret=next(obj) print(ret) except Exception as ret: print(ret.value) break
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| def creat_num(all_num): a,b=0,1 current_num=0 while current_num<all_num: ret=yield a a,b=b,a+b current_num+=1
obj=creat_num(10)
ret=next(obj)
ret=obj.send("123")
|
yeild实现多任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import time
def task_1(): while True: print("1") time.sleep(0.1) yield
def task_2(): while True: print("2") time.sleep(0.1) yield
def main() t1=task_1() t1=task_1()
while True: next(t1) next(t2)
|
gevent实现多任务
gevent一条线程时间片轮转实现多任务
在执行等待操作时切换任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| from gevent import monkey import gevent import random import time
monkey.patch_all()
def coroutine_work(coroutine_name): for i in range(10): print(coroutine_name,i) time.sleep(random.random())
gevent.joinall([ gevent.spawn(coroutine_work,"work1"), gevent.spawn(coroutine_work,"work1") ])
|
总结
- 进程切换资源消耗大,效率一般
- 线程切换需要资源一般,效率一般
- 协程切换任务资源很小,效率高