一、线程
1、一般多线程
1 import time 2 import threading 3 4 5 def sing(): 6 for i in range(5): #调用Thread不会创建线程, 7 print("----test----") #调用Thread创建的实例对象start会创建 8 time.sleep(1) 9 10 def main(): 11 print(threading.enumerate()) #调用Thread之前打印 12 t1 = threading.Thread(target=sing) #调函数名,告诉函数在哪 13 print(threading.enumerate()) #调用Thread之后打印 14 t1.start() 15 print(threading.enumerate()) #调用start之后打印 16 17 18 if __name__ == '__main__': 19 main()
target指定线程去哪执行代码,args指定将来调用传递的数据
当线程t1.start()运行时,会先运行下一行代码,因此运行结果为:
[<_MainThread(MainThread, started 139815265257216)>] [<_MainThread(MainThread, started 139815265257216)>] ----test---- [<_MainThread(MainThread, started 139815265257216)>, <Thread(Thread-1, started 139815239530240)>] ----test---- ----test---- ----test---- ----test----
2、封装多线程为类
1 import threading 2 import time 3 4 5 class MyThread(threading.Thread): 6 def run(self): 7 for i in range(3): 8 time.sleep(1) 9 msg = "I'm "+self.name+'@'+str(i) 10 print(msg) 11 self.login() 12 13 def login(self): 14 print("登陆") 15 16 17 if __name__ =='__main__': 18 t = MyThread() 19 t.start()
MyThread会先自动调用run方法,再通过run方法引入其他函数self.funtion
3、防止CPU资源竞争-互斥锁
1 #创建互斥锁,默认没有上锁 2 mutex = threading.Lock() 3 4 def test1(temp): 5 global g_num 6 #上锁 如果之前没有被上锁,那么此时上锁成功 7 #如果之前上锁了,那么此时会被堵塞,直到解锁 8 mutex.acquire() 9 for i in range(temp): 10 g_num += 1 11 #解锁 12 mutex.release() 13 print("---in test1 temp=%d---" % g_num)
将互斥锁加在for循环内会影响过程变化,执行顺序不同
二、进程
1、内容
进程是资源分配单位,线程是调度单位,线程比进程节省资源;
进程:工厂流水线,线程:工人,线程依赖于进程
1 import multiprocessing 2 from threading import Thread 3 import time 4 5 6 def test1(): 7 while True: 8 print("1------") 9 time.sleep(1) 10 11 def test2(): 12 while True: 13 print("2------") 14 time.sleep(1) 15 16 def main(): 17 t1 = multiprocessing.Process(target=test1) 18 t2 = multiprocessing.Process(target=test2) 19 t1.start() 20 t2.start() 21 22 if __name__ == "__main__": 23 main()
2、队列
先入先出原则,使用put()方法写入,get()方法取出
1 import multiprocessing 2 import time 3 4 5 def download(q): 6 data = [11, 22, 33, 44] 7 #向队列中写入数据 8 for temp in data: 9 q.put(temp) 10 print('已下载完并存入队列') 11 12 def analysis_data(q): 13 '''数据处理''' 14 #从队列中获取数据 15 waitting_analysis_data = list() 16 while True: 17 data = q.get() 18 print(data) 19 waitting_analysis_data.append(data) 20 if q.empty(): 21 break 22 print(waitting_analysis_data) 23 24 25 def main(): 26 #1.创建一个队列 27 q = multiprocessing.Queue() 28 29 #2.创建多个进程,将队列引用当做实参进行传递 30 p1 =multiprocessing.Process(target=download, args=(q,)) 31 print('---p1------') 32 p2 =multiprocessing.Process(target=analysis_data, args=(q,)) 33 print('---p2------') 34 p1.start() 35 36 print('---p1s-----') 37 p2.start() 38 print('---p2s-----') 39 40 41 if __name__ =='__main__': 42 main()
3、进程池
from multiprocessing import Pool import os,time,random def worker(msg): t_start = time.time() print("%S开始执行,进程号为%d" % (msg,os.getid())) #random.random随机生成0~1质检的浮点数 time.sleep(random.random()*2) t_stop = time.time() print(msg,"执行完毕,耗时%0.2f" % (t_stop-t_start)) po = Pool(3) #定义一个进程池,最大进程数3 for i in range(0,10): #Pool().apply_async(要掉用的目标,(传递给目标的参数元祖,)) #每次循环会用空闲出来的子进程去调用目标 po.apply_async(worker,(i,)) print("---start---") po.close() #关闭进程池,关闭后PO不再接受新的请求 po.join() #等待PO种的子进程执行完,必须在close之后 print('---end----')
三、协程
1、迭代与迭代器
1 from collections import Iterable 2 from collections import Iterator 3 import time 4 5 class Classmate(object): 6 def __init__(self): 7 self.names = list() 8 self.current_num = 0 9 def add(self, name): 10 self.names.append(name) 11 12 def __iter__(self): 13 '''如果想要一个对象称为一个 可以迭代的兑现,可以使用for,那么必须实现__iter__方法''' 14 return self 15 #1.判断xxx.obj是否可以迭代 16 #2.调用iter函数得到xxx_obj的_iter_方法返回值 17 #3.返回值是一个迭代器 18 def __next__(self): 19 if self.current_num < len(self.names): 20 ret = self.names[self.current_num] 21 self.current_num += 1 22 return ret 23 else: 24 raise StopIteration 25 26 classmate = Classmate() 27 classmate.add("老王") 28 classmate.add("老二") 29 classmate.add("张三") 30 31 print(iter(classmate)) 32 print("判断classmate是否是可以迭代的对象:",isinstance(classmate, Iterable)) 33 #classmate_iterator = iter(classmate) 34 #print("判断classmate是否是可以迭代的对象:",isinstance(classmate_iterator, Iterable)) 35 #print(next(classmate_iterator)) 36 37 for name in classmate: 38 print(name) 39 time.sleep(1)
2、生成器与传递值
1 def create_num(all_num): 2 a, b = 0, 1 3 current_num = 0 4 while current_num < all_num: 5 ret = yield a #第一次暂停,返回a = 0给next(obj),send值传递给ret 6 print('>>>ret>>>', ret) 7 a, b = b, a+b 8 current_num += 1 9 10 obj = create_num(10) 11 12 ret = next(obj) 13 print(ret) 14 15 ret = obj.send('hahhah') #hahha传递给yield a 16 print(ret)
当函数运行到yield时,函数先暂停运行,并跳过该函数继续往下运行直到遇到next()
1 import time 2 3 4 def task_1(): 5 while True: 6 print("----1----") 7 time.sleep(0.1) 8 yield 9 10 def task_2(): 11 while True: 12 print("----2----") 13 time.sleep(0.1) 14 yield 15 16 def main(): 17 t1 = task_1() 18 t2 = task_2() 19 #先运行t1,当遇到yield时,返回到24行 20 #然后执行t2,遇到yield时切换到t1中 21 #t1/t2交替运行实现多任务,并发协程 22 while True: 23 next(t1) 24 next(t2) 25 26 27 if __name__ =="__main__": 28 main()
3、greenlet
1 from greenlet import greenlet 2 import time 3 4 def test1(): 5 while True: 6 print("---1---") 7 gr2.switch() 8 time.sleep(0.5) 9 10 def test2(): 11 while True: 12 print("---2---") 13 gr1.switch() 14 time.sleep(0.5) 15 16 gr1 = greenlet(test1) 17 gr2 = greenlet(test2) 18 19 gr1.switch()
在函数中定义greenlet().switch(),当主函数switch()时开始运行,来回切换
4、gevent
1 import gevent 2 from gevent import monkey 3 import time 4 5 monkey.patch_all() 6 7 def f1(n): 8 for i in range(n): 9 print(gevent.getcurrent(),i) 10 time.sleep(0.5) 11 def f2(n): 12 for i in range(n): 13 print(gevent.getcurrent(),i) 14 time.sleep(0.5) 15 16 def f3(n): 17 for i in range(n): 18 print(gevent.getcurrent(),i) 19 time.sleep(0.5) 20 21 print("---1----") 22 g1 = gevent.spawn(f1, 5) 23 24 print("---2----") 25 g2 = gevent.spawn(f2, 5) 26 27 print("---3----") 28 g3 = gevent.spawn(f3, 5) 29 30 print("---4----") 31 32 g1.join() 33 g2.join() 34 g3.join() 35 36 gevent.joinall([ 37 gevent.spawn(f1,5) 38 gevent.spawn(f2,5) 39 gevent.spawn(f3,5) 40 ])