多线程主要用于大量的IO操作时的并发执行,以此来提高效率!多进程主要用于大量的计算,进而充分发挥CPU的性能!
这里主要讲述两种多线程的使用:
使用第二种方式需要先安装(对于python2.x)
pip install futures
第一种方式的简单使用:(注意:空白行有删减)
# coding=utf8
import requests
import threading
import concurrent
from concurrent.futures import ThreadPoolExecutor
def task():
url = "https://www.baidu.com"
res = requests.get(url)
if res.status_code == 200:
print "yes!"
else:
print "no!"
def main():
t1 = threading.Thread(target=task) # 用法和Process类很相似
t2 = threading.Thread(target=task)
t1.start()
t2.start()
t1.join()
t2.join()
if __name__ == '__main__':
main()
多线程的可以共享主线程的数据,在操作的时候可能会存在数据不同的问题解决办法是,对于一些代码加锁规定某段时间内只能一个线程访问,直到所被释放!
例子:这个会造成数据不同步
balance = 0
def data_operator(n):
global balance # 表明在这个函数中,balance 是使用的全局的
balance += n
balance -= n
def change_it(n):
for item in xrange(0, 10 ** 6):
data_operator(n)
def thread_synchronization():
t1 = threading.Thread(target=change_it, args=(5,))
t2 = threading.Thread(target=change_it, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
global balance
print balance
# 因为存在变量操作时存在临时变量的使用,在多次执行的时候,操作的数据内容可能存在不同步的情况
# 所以此处打印出的值,不一定是0
balance = 0
main_thread_lock = threading.Lock() # 这里是在主线程中设置的一把线程锁
# 获得锁 main_thread_lock.acquire() 这个方法或阻塞当前线程,直到获得一把锁。但是不会阻塞主线程
# 释放锁 main_thread_lock.release() 此时其他的方法可以去申请锁的使用
# 一般使用try_catch_finally 来确保锁被释放
def data_operator(n):
global balance # 表明在这个函数中,balance 是使用的全局的
balance += n
balance -= n
def change_it(n):
for item in xrange(0, 10 ** 6):
with main_thread_lock: # 这里是在操作主要数据的时候,获得锁,在执行完操作之后将锁释放,这里使用with 语句更加简洁的实现,一定要注意锁的释放
data_operator(n)
使用ThreadPoolExecutor的时候,对于python2.x 需要先安装 pip install futures ,这是在python3中自带的包
基本使用:
import concurrent
from concurrent.futures import ThreadPoolExecutor
def task2(n):
url = "https://www.baidu.com"
res = requests.get(url)
print n
if res.status_code == 200:
return "yes!"
else:
return "no!"
def multi_thread_by_thread_pool_executor():
# max_workers 最多使用的线程数量
with ThreadPoolExecutor(max_workers=5) as executor:
task_list = [executor.submit(task2, x) for x in range(0, 10)]
# 对结果的处理,as_completed 返回一个生成器,等待每一个任务完成的时候就会返回一个任务,参数是futures序列
# item 表示的是Future对象
# 使用 future.result 获取函数结果
for item in concurrent.futures.as_completed(task_list):
print item.result()
不仅仅是对于线程有ThreadPoolExecutor, 对于进程而言,也就ProcessPoolExecutor,使用方式类似,只不过是名字改改
同时由于全局解释器锁的原因,即使很多的线程,CPU 也不能跑满,处分重构解释器,去掉GIL