05-爬虫进阶_多线程(01 基本用法)

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值