进程收尾线程初识

数据共享

from multiprocessing import Manager

把所有实现了数据共享的比较便捷的类都重新又封装了一遍,并且在原有的multiprocessing基础上增加了新的机制list、dict

机制:支持的数据类型非常有限

   list、dict都不是数据安全的,需要自己加锁来保证数据安全

 1 from multiprocessing import Manager,Process,Lock
 2 def work(d,lock):
 3     with lock:
 4         d['count'] -= 1
 5 
 6 if __name__ == '__main__':
 7     lock = Lock()
 8     with Manager() as m:   # m = Manager()
 9         dic = m.dict({'count':100})
10         p_lst = []
11         for i in range(10):
12             p = Process(target=work, args=(dic, lock))
13             p_lst.append(p)
14             p.start()
15         for p in p_lst:
16             p.join()
17         print(dic)
18 #{'count': 90}
数据共享
with ......
    一大段语句
dis模块
python的上下文管理
在执行一大段语句之前,自动做某个操作  open
在执行一大段语句之后,自动做某个操作  close

面向对象的魔术方法
 1 import os
 2 from multiprocessing import Pool
 3 def func(i):
 4     print('第一个任务', os.getpid())
 5     return '*'*i
 6 
 7 def call_back(res):   #回调函数
 8     print('回调函数:', os.getpid())
 9     print('res--->', res)
10 
11 if __name__ == '__main__':
12     p = Pool()
13     print('主进程', os.getpid())
14     p.apply_async(func, args=(1,), callback=call_back)
15     p.close()
16     p.join()
回调函数 in Pool

 func执行完毕之后执行callback函数

func的返回值会作为callback的参数

回调函数是在主进程中实现的

应用场景:子进程有大量运算要做,回调函数等待结果做简单处理

 1 url_lst = [
 2     'http://www.baidu.com',
 3     'http://www.sohu.com',
 4     'http://www.sogou.com',
 5     'http://www.4399.com',
 6     'http://www.cnblogs.com',
 7 ]
 8 import re
 9 from urllib.request import urlopen
10 from multiprocessing import Pool
11 
12 def get_url(url):
13     response = urlopen(url)
14     ret = re.search('www\.(.*?)\.com', url)
15     print('%s finished' % ret.group(1))
16     return ret.group(1),response.read()
17 
18 def call(content):
19     url,con = content
20     with open(url+'.html', 'wb')as f:
21         f.write(con)
22 if __name__ == '__main__':
23     p = Pool()
24     for url in url_lst:
25         p.apply_async(get_url,args=(url,),callback=call)
26     p.close()
27     p.join()
子进程去访问网页,主进程处理网页的结果

 线程理论基础

进程是计算机中最小的资源分配单位,进程对于操作系统来说还具有一定的负担

创建一个进程,操作系统分配的资源大约有:代码,数据,文件等

为什么要有线程

线程是轻量级的概念,他没有属于自己的进程资源,一条线程只负责执行代码,没有自己独立的代码、数据以及文件

线程是计算机中能被CPU调用的最小的单位,当前大部分计算机中的CPU都是执行的线程中的代码

线程与进程之间的关系:每一个进程中都至少有一条线程在工作

线程的特点:

    同一个进程中的所有线程的资源是共享的

    轻量级, 没有自己的资源

进程与线程之间的区别:
    占用的资源、、调度的效率、、资源是否共享

线程的并行问题

线程可以并行:java、c++,c#等

在cpython中,一个进程中的多个线程是不可以并行的

原因是:Cpython解释器内部有一把全局解释器锁GIL,所以线程不能充分利用多核,同一时刻同一进程中的线程只有一个能被cpu执行

GIL锁确实是限制了你程序的效率,但目前可以帮助你提高线程之间切换的效率

如果是想写高计算型的就要多进程或者换一个解释器

threading 模块

1 import os
2 from threading import Thread
3 def func(i):
4     print('子线程:', i, os.getpid())
5 
6 print('主线程', os.getpid())
7 for i in range(10):
8     t = Thread(target=func, args=(i,))
9     t.start()
并发
 1 import os
 2 from threading import Thread
 3 from multiprocessing import Process
 4 import time
 5 def func(i):
 6     print('子:', os.getpid())
 7 
 8 if __name__ == '__main__':
 9     start = time.time()
10     t_lst = []
11     for i in range(100):
12         t = Thread(target=func, args=(i,))
13         t.start()
14         t_lst.append(t)
15     for t in t_lst:
16         t.join()
17     end = time.time()-start
18 
19     start = time.time()
20     t_lst = []
21     for i in range(100):
22         p = Process(target=func, args=(i,))
23         p.start()
24         t_lst.append(p)
25     for p in t_lst:
26         p.join()
27     end2 = time.time()-start
28     print(end, end2)
29 #0.0279843807220459 13.582834720611572
进程和线程的差距
 1 from threading import Thread
 2 num = 100
 3 def func():
 4     global num
 5     num -= 1            #每个线程都-1
 6 
 7 t_lst = []
 8 for i in range(100):
 9     t = Thread(target=func)   #创建一百个线程
10     t.start()
11     t_lst.append(t)
12 for t in t_lst:
13     t.join()
14 print(num)   #0
线程间的数据共享

Thread 类的其他用法

Thread实例对象的方法
  # isAlive(): 返回线程是否活动的。
  # getName(): 返回线程名。
  # setName(): 设置线程名。

threading模块提供的一些方法:
  # threading.currentThread(): 返回当前的线程变量。
  # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
 1 from threading import currentThread,Thread
 2 def func():
 3     time.sleep(2)
 4 
 5 t = Thread(target=func)
 6 t.start()
 7 print(t.is_alive())    #True(判断线程是否活着)
 8 print(t.getName())  #Tread-1
 9 t.setName('tt')
10 print(t.getName())   #tt(改名字)
11 
12 def func():
13     print('子线程:', currentThread().ident)
14     time.sleep(2)
15 print('主线程:',currentThread().ident)
16 t = Thread(target=func)
17 t.start()
18 #currentThread().ident返回线程的pid
19 
20 from threading import enumerate
21 def func():
22     print('子进程:', currentThread().ident)
23     time.sleep(2)
24 
25 print('主进程:', currentThread().ident)
26 for i in range(10):
27     t = Thread(target=func)
28     t.start()
29 print(len(enumerate()))
30 #enumerate()返回一个包含正在运行的线程的list,len(list)
31 
32 from threading import activeCount
33 def func():
34     print('子线程:', currentThread().ident)
35     time.sleep(2)
36 
37 print('主线程:', currentThread().ident)
38 for i in range(10):
39     t = Thread(target=func)
40     t.start()
41 print(activeCount())
42 #activeCount()返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
示例

 守护线程

 1 import time
 2 from threading import Thread
 3 def func():
 4     while True:
 5         time.sleep(1)
 6         print(123)
 7 
 8 def func2():
 9     print('func2 start')
10     time.sleep(3)
11     print('func2 end')
12 
13 t1 = Thread(target=func)
14 t2 = Thread(target=func2)
15 t1.setDaemon(True)
16 t1.start()
17 t2.start()
18 print('主线程代码结束')
19 # func2 start
20 #主线程代码结束
21 #123
22 #123
23 #func2 end
代码

守护线程 是在主线程代码结束之后,再等待子线程执行结束后才结束

主线程结束  就意味着主进程结束

主线程等待所有的线程结束

主线程结束了以后  守护线程会随着主进程的结束而随之结束  不是随着代码的结束而结束

 

 

 

######################################

# 线程
# 线程和进程之间的关系
# 每个进程内都有一个线程
# 线程是不能独立存在的
# 线程和进程之间的区别
# 同一个进程中线程之间的数据是共享的
# 进程之间的数据是隔离的
# 线程是被cpu执行的最小单位
# 操作系统调度
# 进程是计算机中最小的资源分配单位
# python
# GIL锁 全局解释器锁 全局锁
# cpython解释器中的
# 锁线程 :同一时刻同一个进程只会有一个线程访问CPU
# 锁的是线程而不是数据
# 当程序是高IO型的 多线程
# 当程序是高计算(CPU)型的 多进程
# cpu*1 ~ cpu*2

# threading
# Thread
# 守护线程 :主线程结束之后才结束

# socket_server IO多路复用 + 多线程
# 框架 并发的效果 :多线程、协程的概念 flask
# 爬虫 :线程池 协程

# set、dict、list
# 生成器
# 面向对象的进阶 :魔术方法
# 管道
# socket_server的源码
posted @ 2018-09-21 15:25  .why  阅读(243)  评论(0)    收藏  举报
Live2D