L14_多线程爬虫

多线程基本介绍

有很多场景中的事是同时进行的,比如开车的时候手和脚共同来驾驶汽车,再比如唱歌跳舞同时进行


如何创建线程

· 方法一:通过函数

   使用 threading 模块中的Thread类, 在这个类中有一个target参数需要传递一个函数对象。而这个函数内,就是多线程的逻辑

 · 方法二:通过类的方式

    创建一个类,当时这个类需要基础threading.Thread。并实现(重写) run()方法。在 run() 方法中实现多线程的逻辑

主线程和子线程的执行优先级

· 主线程会等待子线程结束之后再结束

· join(),等待子线程全部结束后,主线程序才继续执行


· setDaemon() 守护线程,不会等待子线程结束,主线程先行结束

程序中模拟多任务

验证子线程的执行与创建

当调用Thread的时候,不会去创建线程

当调用Thread创建出来的实例对象的start方法的时候,才会创建线程以及开始运行这个线程

enumerate()用来查看当前活动线程的数量


线程间共享全局变量

在一个函数中,对全局变量进行修改的时候,是否要加global要看是否对全局变量的指向进行了修改,如果修改了指向,那么必须使用global,仅仅是修改了指向的空间中的数据,此时不用必须使用global, 线程是共享全局变量的

线程间的资源竞争

一个线程写入,一个线程读取,如果两个线程都写入呢?

互斥锁和死锁

· 互斥锁

当多个线程几乎同时修改一个共享数据的时候,需要进行同步控制

某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其它线程不能改变。

只到该线程释放资源,将资源的状态变成“非锁定”,其它的线程才能再次锁定该资源。

互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

创建锁

mutex = threading.Lock()

锁定

mutex. acquire()

解锁

mutex.release()

  · 死 锁

    在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁

· 通过Threading.Lock()创建的锁是不可重复的锁

  也就是mutex.acquire()  与mutex.release()是成对出现的。

  不能出现 mutex.acquire() 后又重复跟了一个 mutex.acquire()

· 避免死锁

  · 程序设计时要尽量避免

  · 添加超时时间

Queue 线程

在线程中,访问一些全局变量,加锁是一个经常的过程。如果是想把一些数据存储到某个队列中,那么python内置了一个线程安全的模块叫做queue模块。

python 中的queue模块中提供了同步的、线程安全的队列类,包括FIFO(进先出)队列)队列Queue,

LIFO( 先入后出 )队列LifoQueue

这些队列都实现 了锁原语(可以理解为原子操作,要么不做,要么都做完),能够在多线程中直接使用。可以使用队列来实现线程间的异步


生产者和消费者

生产者和消费者模式是多线程开发中常见的一种模式。通过生产者和消费者模式,可以让代码达到高内聚低耦合的目标,线程管理更加方便,程序分工更加明确。

生产者的线程专门用来生产一些数据,然后存放到容器中(中间变量)。消费者在从这个中间的容器中取出数据进行消费

Lock版生产者与消费者示例:

Condition版的生产者和消费者示例:

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容