1-多线程概念和threading模块介绍
多线程爬虫
有些时候,比如下载图片,因为下载图片是一个耗时的操作,如果采用之前那种同步的方式下载。那效本育会特别慢。这时候我们款可以考虑使用多线程的方式未下图片
多线程介绍
多线程是为了同步完成多项任务,通过提高资源使用效事来提高系统的效率。线程是在同一时间要完成新任务的时候实现的。最简单的比喻多线程就像火车的每一节车题,而进程则是火车,车厢离开火车是无法跑动的,同理火车也可以有多节车。多线程的出现就是为了提高效率,同时它的出现也带来了一些问题。
threading模块介绍
python自带的模块,无需安装。threading模快是pythen中专门提供用来做多线程编程的模块,threading模块中最常用的类是Thread。
1)传统方式执行:【总的会花费6秒的时间】
# 一、传统方式执行:【总的会花费6秒的时间】
import time
def coding():
for x in range(3):
print('正在写代码%s' %x)
time.sleep(1)
def drawing():
for x in range(3):
print('正在画图%s' %x)
time.sleep(1)
def main():
coding()
drawing()
if __name__== '__main__':
main()
2)采用多线程方式:【总的只用花费3秒时间】
# 二、采用多线程方式:【总的只用花费3秒时间】
import threading
import time
def coding():
for x in range(3):
print('正在写代码%s' %x)
time.sleep(1)
def drawing():
for x in range(3):
print('正在画图%s' %x)
time.sleep(1)
def main():
t1 = threading.Thread(target=coding) # 注意:这里不能用coding(),因为加了括号后表示返回结果,这里不加括号,只表示这段代码
t2 = threading.Thread(target=drawing)
t1.start()
t2.start()
if __name__== '__main__':
main()
2-使用Thread类创建多线程
继承自threading.Thread类:
为了让线程代码更好的封装。可以使用treading模块下的Thread类,继承自这个类,然后实观run方法,线程数会自动运行run方法中的代码。
- 查看线程数:使用threading.enumerate()函数便可以看到当前线程的数量。
- 查看当前线程的名字:使用threading.current_thread()可以看到当前线程的信息。
1)多线程创建的方式一
# 多线程创建的方式1:
import threading
import time
def coding():
for x in range(3):
print('正在写代码%s' %threading.current_thread()) # 打印当前进程
time.sleep(1)
def drawing():
for x in range(3):
print('正在画图%s' %threading.current_thread())
time.sleep(1)
def main():
t1 = threading.Thread(target=coding)
t2 = threading.Thread(target=drawing)
t1.start()
t2.start()
if __name__== '__main__':
main()
2)多线程创建的方式二
# 多线程创建的方式2:
import threading
import time
class CodingThread(threading.Thread):
def run(self):
for x in range(3):
print('正在写代码%s' %threading.current_thread())
time.sleep(1)
class DrawingThread(threading.Thread):
def run(self):
for x in range(3):
print('正在画图%s' %threading.current_thread())
time.sleep(1)
def main():
t1 = CodingThread()
t2 = DrawingThread()
t1.start()
t2.start()
print(threading.enumerate()) # 打印总的进程数量,这里是3个进程
if __name__ == '__main__':
main()
3-多线程共享全局变量以及锁机制
多线程共享全局变量的问题
多线程都是在同一个进程中运行的,因在进程中的全局变量所有线程都是可共享的,这就造成了一个问题,因为线程执行的顺序是无序的。有可能会造成對据错误。比如以下代码:
import threading
tickets = 0
def get_ticket():
global tickets
for x in range(1000000):
tickets += 1
print('tickets:%d'%tickets)
def main():
for x in range(2):
t = threading.Thread(target=get_ticket)
t.start()
if __name__ == "__main__":
main()
以上结果正常来讲应该是6,但是因为多线程运行的不确定性,因此最后的结果可能是随机的。
为了防止以上现象需要加上锁,代码如下:
import threading
VALUE = 0
gLock = threading.Lock()
def add_value():
global VALUE
gLock.acquire()
for x in range(1000000):
VALUE += 1
gLock.release()
print('value: %d'%VALUE)
def main():
for x in range(2):
t = threading.Thread(target=add_value)
t.start()
if __name__ == "__main__":
main()
注意:
- 以上代码有2个子进程,不同时修改value,如果不上锁可能出错。
- 在函数中需要用到全局变量,首先需要申明,如:global VALUE