标签:src callback bsp future 动态 random mit range res
线程
在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程
线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程
车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线
流水线的工作需要电源,电源就相当于cpu
所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。
多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。
例如,北京地铁与上海地铁是不同的进程,而北京地铁里的13号线是一个线程,北京地铁所有的线路共享北京地铁所有的资源,比如所有的乘客可以被所有线路拉。
开启线程的两种方式
from threading import Thread
import time,os
# 第一种方式
def task():
print(‘%s is running‘ %os.getpid())
time.sleep(2)
print(‘%s is done‘ %os.getpid())
if __name__ == ‘__main__‘:
t = Thread(target=task,)
t.start()
print(‘主‘)
‘‘‘
1.一个子进程内不开进程也不开子线程:主线程结束,该进程就结束
2.当一个进程内开启子进程时:
主线程结束,主进程要等,等所有子进程运行完毕给儿子收尸
3.当一个进程内开启多个线程时:
主线程结束并不意味着进程结束,
进程的结束指的是该进程内所有的线程都运行完毕,才应该回收进程
‘‘‘
# 第二种方式
class Mythread(Thread):
def __init__(self):
super().__init__()
def run(self):
print(‘%s is running‘ % os.getpid())
time.sleep(2)
print(‘%s is done‘ % os.getpid())
if __name__ == ‘__main__‘:
t = Mythread()
t.start()
print(‘主‘)
多线程指的是,在一个进程中开启多个线程,简单的讲:如果多个任务共用一块地址空间,那么必须在一个进程内开启多个线程。详细的讲分为4点:
1. 多线程共享一个进程的地址空间
2. 线程比进程更轻量级,线程比进程更容易创建可撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用
3. 若多个线程都是cpu密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度。
4. 在多cpu系统中,为了最大限度的利用多核,可以开启多个线程,比开进程开销要小的多。(这一条并不适用于python)
线程对象的其它属性和方法
from threading import Thread,current_thread,enumerate,active_count
import time,os
def task():
print(‘%s is running‘ %current_thread().getName()) # 线程名 current_thread()当前线程
time.sleep(2)
print(‘%s is done‘ %os.getpid())
if __name__ == ‘__main__‘:
# t = Thread(target=task,name=‘xxx‘)
t = Thread(target=task)
t.start()
# t.join()
# print(t.name) # 线程名 Thread-1
print(enumerate()) # 当前或者的线程对象
print(active_count()) # 当前活着线程的线程数
print(‘主‘,current_thread().getName()) # MainThread
线程与进程内存空间占用
# 进程之间内存空间隔离
from multiprocessing import Process
n = 100
def task():
global n
n = 0
if __name__ == ‘__main__‘:
t = Process(target=task,)
t.start()
t.join()
print(‘主‘,n) # 100
# 线程之间内存空间共享
from threading import Thread
n = 100
def task():
global n
n = 0
if __name__ == ‘__main__‘:
t = Thread(target=task,)
t.start()
t.join()
print(‘主‘,n) # 0
线程池
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import current_thread
import time,random,os
def task(n):
print(‘%s is running‘%current_thread().getName())
time.sleep(random.randint(1,3))
return n**2
if __name__ == ‘__main__‘:
# t = ProcessPoolExecutor() # 默认是cpu的核数
# print(os.cpu_count()) # 查看cpu核数
t = ThreadPoolExecutor(3) # 默认为cpu的核数*5
objs = []
for i in range(10):
obj = t.submit(task,i)
objs.append(obj)
t.shutdown(wait=True)
for obj in objs:
print(obj.result())
print(‘主‘,current_thread().getName())
异步调用和回调函数
import requests
from threading import Thread,current_thread
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time
def get(url):
print(‘%s GET %s‘%(current_thread().getName(),url))
response = requests.get(url)
if response.status_code == 200:
return {‘url‘:url,‘text‘:response.text}
# print(type(response.text)) # <class ‘str‘>
def parse(obj):
res = obj.result()
print(‘[%s] <%s> (%s)‘ % (current_thread().getName(), res[‘url‘],len(res[‘text‘])))
# print(‘[%s] parse res [%s]‘%(res[‘url‘],len(res[‘text‘])))
if __name__ == ‘__main__‘:
urls = [
‘https://www.python.org‘,
‘https://www.baidu.com‘,
‘https://www.jd.com‘
]
t = ThreadPoolExecutor(2)
# t = ProcessPoolExecutor(2)
for url in urls:
t.submit(get,url).add_done_callback(parse) # parse(obj)
t.shutdown(wait=True)
print(‘主‘)
‘‘‘
异步调用:
提交完任务(为该任务绑定一个回调函数),不用在原地等任务执行完毕拿到结果,可以直接提交下一个任务
一个任务一旦执行完毕就会自动触发回调函数的运行
回调函数的参数是单一的:
回调函数的参数就是它所绑定任务的返回值
‘‘‘
# 进程池,回调的活由主进程干
# 线程池,回调的活都有可能干
标签:src callback bsp future 动态 random mit range res
原文地址:http://www.cnblogs.com/QQ279366/p/7954325.html