Python 线程进阶篇 | 多线程下载网页[亲测有效]

Python 线程进阶篇 | 多线程下载网页[亲测有效]分享多线程编程。

Python 线程进阶篇 | 多线程下载网页[亲测有效]


Python的并发编程前面只讲了进程和线程的入门篇,线程里面还有很多有用而好玩的招式,我们还没有讲,我一直主张学一门语言一定要有兴趣,带着玩Python的心态去学,会轻松很多,打个比方打扫卫生和打羽毛球,可能都很累,为啥你打球就很high,而在家打扫卫生就很累,因为你enjoy打球哈哈,好言归正传,今天我们就来讲讲多线程编程~~

要点:

线程的同步

线程的锁

线程的通讯

1.线程如何同步

1).若主程序创建了一个线程之后,启动线程start().线程的一个关键特性是每个线程都是独立运行且状态不可预测

我们希望线程启动运行后,线程内部运行到某种情况的时候,主程序才执行

比如程序中的其他线程需 要通过判断某个线程的状态来确定自己下一步的操作

这时线程同步问题就会变得非常棘手,怎么破,很简单,利用线程threading.Event(),来设置信号量来控制

Python 线程进阶篇 | 多线程下载网页[亲测有效]


>>

Start thread1…

1

2

3

Start to run in main function

4

5

6

主程序创建一个Event()对象my_event,把my_event传到子线程里面

在子线程里面设置my_event.set()也就是说子线程运行到i==4时把信号量置为True而外边的主函数my_event.wait()一直阻塞在那里,傻傻的等着信号量的状态

一旦set()了意味着信号量为True了,外边主函数就可以开始行动了

2).同样我们假设有2个子线程,那两个子线程之间的同步也可以用Event来搞定

Python 线程进阶篇 | 多线程下载网页[亲测有效]


>>

Start thread1…

1

2

3

4

Ok,we can start thread2…

5

6

线程thread1和线程wait_for_thread1通过Event()对象来设置信号量,通过这个信号量来进行两个子线程的同步

2. 线程的锁

在多线程中,由于所有的变量都由所有线程共享,所以在运行的过程中,任何一个变量都可以被任何一个线程修改

因此,线程之间共享数据会有risk,很可能跑着跑着,数据就被别人改了,所以我们需要加锁来控制

举一个非常经典的例子,就是银行存取款的,相信很多同学都听说过这个例子,在传统的c++,java里面也大量用这个例子来说明锁的重要性,我们来看一下

1).假设银行存款有1000元,有两个线程对这笔钱进行操作

我再存1块钱,然后再取1块钱

我再存10块钱,然后再取10块钱

理论上讲无论多少次,这笔钱应该还是1000块,但是当两个线程同事进行大量频繁的操作的时候,诶情况就有变化了,钱多了,或者少了,不信你看

Python 线程进阶篇 | 多线程下载网页[亲测有效]


>>

1097

[Finished in0.3s]

哇多了97块钱,真是好事啊,哈哈,银行肯定不乐意了,要找原因了

11).我们在算钱的时候,做了两步

第一步:balance=balance+n

第二步:balance=balance-n

12).底层操作系统在执行的时候会分成好几步去执行,python是有C写的,C又会变成汇编语言去执行指令,所以当两个线程频繁的操作的时候,中间的指令会被打断,从而导致多个线程把同一个变量的内容改乱了(当然我们是希望钱变多哈哈)

2).所以一般对于多线程处理核心的数据,都是要加锁的

就是让某一个时刻,只能有一个线程改这个变量,让这个线程执行完了,释放锁,再让下一个线程执行,保证核心数据不会被改乱了~~比如我们执行10,100万次存取,都不会出差错

Python 线程进阶篇 | 多线程下载网页[亲测有效]


>>

1000

[Finished in1.1s]

创建一个threading.Lock()对象,在处理核心数据操作的时候,先锁起来,用完再释放锁,看现在反复操作100000次,钱还是1000,一分没有少,大家有没有发现一个问题,这个是有代价的,就是运行开销很大,原来是0.3s运行完,现在要1.1s才能搞定

3. 线程之间的通信

好比我有一个工作要做,一个线程要干6分钟,那么我创建3个线程,同时去处理这些事情,是不是只要2分钟.效率高了许多.

那么怎么样才能让这些线程之间实现安全的通信或者交换数据呢

Python里面有一个高效安全的Queue模块,我们主需要把数据塞进队列,它就会被所有的线程共享

然后用put()或者get()操作来给队列添加或者移除元素

我们举一个多线程爬网页的例子吧

Python 线程进阶篇 | 多线程下载网页[亲测有效]


1).首先创建一个DownloadThread类,这个类继承threading.Thread

2).类的初始化函数,留一个接口,把queue带进去,这样所有的线程都可以共享这个queue

3).类的run函数,设计成死循环,不断的从队列里面取数据,一旦这个线程把从这个队列里面的数据取完了,就调用queue.task_done()表示我已经干完了

4).类的download_file函数,其实就是具体去执行下载网页的工作,因为爬虫后面再讲,所以我这边只用了很简单的urllib.urlopen()函数,简单获取网页而已

接着看main函数

Python 线程进阶篇 | 多线程下载网页[亲测有效]


>>

Thread-3:begin dowbload http://wiki.python.org/moin/WebProgramming…

Thread-1:begin dowbload https://wiki.python.org/moin/WebFrameworks…

Thread-2:begin dowbload https://wiki.python.org/moin/BeginnersGuide…

Thread-2 download completed

Thread-2:begin dowbload https://wiki.python.org/moin/PythonBooks…

Thread-1 download completed

Thread-1:begin dowbload https://wiki.python.org/moin/PythonEvents…

Thread-2 download completed

Thread-1 download completed

Thread-3 download completed

Cost time:0:00:14.604000

1).main函数里面我们设定了有5个网页要爬

2).启动3个线程,并且设定为守护线程,就是当main()函数一结束,所有的子线程全部结束

3),把5个网页(也可以认为是5个要完成的task),这里是要爬网页,以后你可以变成其他数据结构,或者直接封装成类然后塞进queue里面,让这3个线程去共享完成.

4).queue会阻塞在哪里,等到所以的线程完成那一刻

5).大家看Thread2完成了之后,又会接着去爬下一个网页(真是个勤快的孩子),Thread1也是完成之后接着去爬下一个,看起来Thread3执行的网页爬的最慢

6).最后计算一下时间,大家改一下代码,可以比较一下一个线程爬5个网页和3个线程同时去快多少(大概是3倍)

补充说一下,这个爬网页urlopen()没有加任何异常保护,当然在实际操作中是肯定要保护,并且当出现异常的时候要设置一个flag来通知线程终止的.


需要源码后台留言

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13544.html

(0)

相关推荐

  • 20200618_MySQL学习笔记

    20200618_MySQL学习笔记加号 + Mysql中加号只能做运算符 select 100+90 ==> 190 select '100'+90 ==> 190 如果有一个是字符串,那么尝试转换成数值型,转换…

    2023-03-14
    126
  • JDBC-用程序操作数据库「建议收藏」

    JDBC-用程序操作数据库「建议收藏」一、JDBC JDBC:Java Database Connectivity 驱动:每个数据库厂商对JDBC的接口的实现类。 二、JDBC程序的开发步骤 1、引入驱动jar 2、编写代码 三、JDB…

    2023-02-14
    109
  • Redis学习笔记(七) 数据库[通俗易懂]

    Redis学习笔记(七) 数据库[通俗易懂]Redis 服务器将所有的数据库都保存在服务器状态redisServer结构的db数组中,db数组的每个项都是一个redisDB: struct redisServer{ //一个数组保存着服务器中的

    2023-02-28
    106
  • Python os.path.join函数的使用方法

    Python os.path.join函数的使用方法在Python中,os模块经常被用来进行文件系统操作。os.path.join()函数是os模块中非常重要的一个函数,它可以用来将多个路径组合成一个路径。

    2024-01-02
    64
  • clickhouse 预聚合_clickhouse入门

    clickhouse 预聚合_clickhouse入门上篇笔记讲到了聚合函数的实现并且带大家看了聚合函数是如何注册到ClickHouse之中的并被调用使用的。这篇笔记,笔者会续上上篇的内容,将剖析一把ClickHouse聚合流程的整体实现。 第二篇文章,

    2023-03-22
    104
  • 提高 Python 代码效率的实用技巧

    提高 Python 代码效率的实用技巧Python 是一种相对较慢的编程语言,但它非常流行并且有很多便于使用的库和工具。如果你正在使用 Python 编写大量的代码,那么如何提高代码的效率呢?在本文中,我们将从多个方面探讨 Python 代码的效率,并介绍一些实用技巧,以帮助大家更快地编写高效的 Python 代码。

    2023-12-06
    70
  • Python中UTC时间的秒数转换

    Python中UTC时间的秒数转换UTC时间是世界协调时间,也被称为格林威治标准时间(GMT)。它是以英国伦敦的本初子午线为基准,用作全球标准时间。UTC时间不像当地时间会受到夏令时的影响,因此在全球的通讯、航空等领域都广泛应用。

    2023-12-31
    60
  • Python开发环境搭建

    Python开发环境搭建Python是一种高级编程语言,旨在提供一种简单易学的编程方式,同时也应用广泛。Python在数据分析、Web开发、机器学习和人工智能等领域都得到广泛应用。因此,Python成为了一种非常有用的编程语言,也吸引了越来越多的学习者。在本篇文章中,我们将对Python的开发环境搭建进行详细介绍,帮助初学者搭建一个合适的Python开发环境。

    2024-05-10
    14

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注