一、线程

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)
mutex锁

  将互斥锁加在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----')
进程池

 

4、显示进度

 1 import os
 2 from multiprocessing import Pool
 3 import multiprocessing
 4 from multiprocessing import Manager
 5 
 6 
 7 def copy_file(q,file_name, old_folder, new_folder):
 8     #完成文件的复制
 9     print("模拟copy文件:从%s复制%s到%s" % (old_folder, file_name, new_folder))
10     older_f =  open(old_folder + "/" + file_name, "rb")
11     content = older_f.read()
12     older_f.close()
13     
14     new_f = open(new_folder + "/" +file_name, "wb")
15     new_f.write(content)
16     new_f.close()
17     #如果拷贝完文件,那么向队列写入一个消息表示完成
18     q.put(file_name)
19 
20 
21 def main():
22     #1.获取用户要copy的文件夹名字
23     old_folder = input("请输入文件夹名字:")
24         
25     #2.创建一个新的文件夹
26     try:
27         new_folder = old_folder + "[复件]"
28         os.mkdir(new_folder)
29     except:
30         pass
31 
32     #3.获取文件夹的所有待copy文件名字
33     file_names = os.listdir(old_folder)
34     print(file_names)
35 
36     #4.创建进程池
37     po = Pool(5)
38     #6.创建一个队列
39     q = Manager().Queue()
40 
41     #5.向进程池中添加copy文件的任务
42     for file_name in file_names:
43         po.apply_async(copy_file, args=(q, file_name, old_folder, new_folder))
44         
45 
46     #复制文件夹中的文件,到新文件夹中的文件去
47     
48     po.close()
49    # po.join()
50     all_file_num = len(file_names)
51     copy_num = 0
52     while True:
53         file_name = q.get()
54         #print("已经完成copy: %s" % file_name)
55         copy_num+=1
56         print("\r拷贝进度为: %.2f %%" % (copy_num*100/all_file_num),end="")
57         if all_file_num == copy_num:
58             break
59 
60     print()
61 
62 
63 if __name__ == "__main__":
64     main()
显示进度

 

三、协程

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与send

  当函数运行到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()
yield运行顺序

 

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运行方法

  在函数中定义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     ])
gevent运行方法
  g1 = gevent.spawn(function,arg())
  g1.join()
  monkey.patch_all()自动校正延时time.sleep()为gevent.sleep()
  gevent.joinall([gevent.spawn()])添加多个spawn

 四、总结(个人理解)

1、节省资源方面:协程>线程>进程,程序稳定性方面则反之

2、协程利用线程运行等待的时间,去运行其他任务,切换任务资源小

   线程资源一般,效率一般

   进程给线程分配CPU的资源,让线程各自运行任务,切换任务资源大,因此耗费资源最多

posted on 2019-06-30 22:48  喻解  阅读(744)  评论(0编辑  收藏  举报