python开启多线程。
使用的库:
python 3.+ :threading(较高级,常用), _thread(python2.+中叫 thread)(偏底层)
python 2.+ :thread
实现多线程:(python3.6,使用 threading 库)
1:函数实现
#第一种:通过函数创建线程
def 函数a():
pass
# 获得一个线程对象。
t = threading.Thread(target=函数a的名字,name=自己随便取的线程名字,args=(参数1,...))
# 启动线程
t.start();
2:继承线程类(类实现)
class Fetcher(threading.Thread):
def __init__(self):
Thread.__init__(self):
#加这一步的目的是保证,主线程退出后子线程也会跟着中断退出
self.daemon = True
# 必须要写
def run(self):
#线程运行的函数
pass
# 获得对象,并启动线程
t = Fetcher()
t.start()
锁:
线程同时操作一个全局变量时会产生线程竞争所以,需要锁来避免竞争。
实现锁:
lock = threading.Lock()
lock.acquire() #获得锁,加锁
#..操作全局变量..(写文件,写入数据库等)
lock.release() #释放锁
队列:(线程池中使用)
多线程同步就是多个线程竞争一个全局变量时按顺序读写,一般情况下要用锁,但是使用标准库里的Queue的时候它内部已经实现了锁,不用程序员自己写了。
使用队列(只介绍在线程池中的常用方法):
# 导入队列类:
from queue import Queue
# 创建一个队列:
q = Queue(maxsize=0) # maxsize为队列大小,为0默认队列大小可无穷大。
# 队列是先进先出的数据结构:
q.put(item) #往队列添加一个item,队列满了则阻塞
q.get(item) #从队列得到一个item,队列为空则阻塞
还有相应的不等待的版本,这里略过。
队列不为空,或者为空但是取得item的线程没有告知任务完成时都是处于阻塞状态
q.join() #阻塞直到所有任务完成
# 线程告知任务当前任务已结束,可以开始下次任务使用 task_done() 函数
q.task_done() #在线程内调用
==============================实现简单线程池(爬虫使用)==================================
1:创建一个线程类:
class TestThread(threading.Thread):
def __init__(self,task,lock):
threading.Thread.__init__(self);
self.task = task ; # 一个队列,用来存放要爬取的url
self.lock = lock ; # 一个锁对象,用来保护存入数据库等的操作
self.daemon = True; # 当主线程退出时,子线程也退出。
self.start(); # 运行当前线程。
# 线程中的主运行方法
def run(self):
while True:
# 从队列中获取url,若没有则一直阻塞,直到获取到一个url。
url = self.task.get();
"""
这里进行爬数据的操作
"""
# 向任务禀报当前任务执行结束,可以开始下一任务
self.task.task_done();
2:创建一个线程池类
class ThreadPool():
def __init__(self,thread_num,lock):
self.task = queue.Queue(); # 生成一个队列,用来存储要爬取的连接
self.lock = lock; # 一个锁对象,用来保护写入文件
# 根据传入的线程数目,创建对应个线程
for i in range(thread_num):
TestThread(self.task,lock);
def add_task(self,url):
# 往队列中放url,直到队列满则阻塞。
self.task.put(url)
def wait_complite(self):
# 阻塞队列中的所有线程,直到主线程执行完毕
self.task.join();
3:使用
if __name__ == "__main__":
print("开始于:",start)
lock = threading.Lock();
pool = ThreadPool(2,lock);
for i in range(21):
pool.add_task(i)
pool.wait_complite();
print("主线程结束");
print("共用时:",time.time()-start)