day7 多线程和多进程

本文详细介绍了线程和进程的概念,强调了线程作为进程执行任务的基本单位,阐述了多线程在提高程序执行效率方面的优势。通过实例展示了如何创建和管理线程,包括主线程、子线程以及线程的串行执行和并行执行。此外,还讲解了线程阻塞和多进程的概念,包括进程的创建、启动和阻塞。最后,通过实际的图片下载案例说明了多线程和多进程在实际问题中的应用。
摘要由CSDN通过智能技术生成

多线程和多进程

01 . 什么是线程和进程

  • 什么是进程 - 工厂

    • 一个正在运行的应用程序就是一个进程。
    • 每一个进程均运行在其钻用且受保护的内存(运行内存)中
  • 什么是线程 - 工人

    • 线程就是进程执行任务的基本单位,进程要做什么事情,必须要与线程。
  • 线程的特点 - 串行

    • 如果在一个线程中执行多个任务,任务是串行执行的(一个一个的按照顺序执行)
  • 多线程

    • 默认情况下,一个进程只有一个线程,多线程指的是在一个进程中有多个线程。
    • 多线程执行不同的任务可以并行(同时)执行。
    • 注意:多线程可以提高程序执行效率,但并不是越多越好(计算机一般的应用程序不要超过100个,爬虫可以达到200-300个)

02 . 多线程

  • 主线程和子线程

    • 一个进程默认只有一个线程,这个进程叫主线程。除了主线程以外的线程叫子线程。

    • 如果进程中需要子线程,只能自己创建(创建线程类或者线程类的子类对象)

      from threading import Thread,current_thread
      
      print(current_thread())             # <_MainThread(MainThread, started 6448)>
      
  • 单线程的串行

    def download(name):
        print(f'{name}开始下载:{datetime.now()}')
        time.sleep(2)
        print(f'{name}开始结束:{datetime.now()}')
    
    download('123')
    download('456')
    download('789')
    
  • 创建三个子线程,下载散步电影

    • 创建线程对象,并且分配线程任务:Thread(*,target,args)

      target - 需要在子线程中调用的函数,需要给一个普通函数的函数名(代表任务)。

      args - 在子线程中调用target对应的函数的时候需要的参数对应的元组。如果需要一个实参,元组就给一个元素,如果需要两个实参,元组就给两个元素…

    • 启动线程:线程对象 . start()

      import time
      from threading import Thread,current_thread
      from datetime import datetime
      
      # print(current_thread())
      
      def download(name):
          print(f'{name}开始下载:{datetime.now()}')
          time.sleep(2)
          print(f'{name}开始结束:{datetime.now()}')
      
      # download('123')
      # download('456')
      # download('789')
      
      t = Thread(target=download,args=('123',))
      t1 = Thread(target=download,args=('456',))
      t2 = Thread(target=download,args=('789',))
      
      t.start()
      t1.start()
      t2.start()
      

03 . 图虫图片一步下载

from selenium.webdriver import Chrome
import time
from lxml import etree
from threading import Thread
import requests
import os
from datetime import datetime

b = Chrome()


def download_image(url):
    print(f'开始下载.....:{datetime.now()}')
    res = requests.get(url)
    image_name = os.path.basename(url)
    open(f'files/{image_name}', 'wb').write(res.content)
    print(f'图片下载完成!{datetime.now()}')


def get_html():
    # 1. 获取图片地址
    b.get('https://stock.tuchong.com/topic?topicId=50346')
    time.sleep(1)
    html = etree.HTML(b.page_source)
    result = html.xpath('//div[@class="justified-layout"]/div/div/@data-lazy-url')

    # 2. 下载图片
    print('==================开始下载===================')
    for img_url in result:
        t = Thread(target=download_image, args=('https:'+img_url,))
        t.start()


if __name__ == '__main__':
    get_html()

04 . 线程阻塞

  • 阻塞线程 - 等到某个线程的任务结束才接着执行

  • 线程对象 . join()

    import time
    from threading import Thread,current_thread
    from datetime import datetime
    from random import randint
    
    def download(name):
        print(f'{name}开始下载:{datetime.now()}')
        time.sleep(randint(2,10))
        print(f'{name}下载结束:{datetime.now()}')
    
    
    t = Thread(target=download,args=('123',))
    t1 = Thread(target=download,args=('456',))
    t2 = Thread(target=download,args=('789',))
    
    # 需求1:等到电影全部下载完成(三个线程都结束)才开始打印
    # t.start()
    # t1.start()
    # t2.start()
    # t.join()
    # t1.join()
    # t2.join()
    # print('=======电影全部下载完成========')
    
    # 需求2:第一个电影下载完成后才开始下载2、3个电影
    t.start()
    t.join()
    t1.start()
    t2.start()
    
    =========================华丽的分割线===============================
    names = ['肖申克的救赎', '触不可及', '头脑特工队', '恐怖游轮']
    ts = []
    for name in names:
        t = Thread(target=download, args=(name,))
        t.start()
        ts.append(t)
    
    for t in ts:
        t.join()
    
    # 要求: 所有电影都下载结束打印 '全部下载完成'
    print('=============全部下载完成=============')
    

05 . 多进程

  • 多进程

    • 一个应用程序默认只有一个进程(主进程),每一个进程中默认有一个线程(主线程)
    • 一个程序可以有多个进程(除了主进程以外的进程叫子进程),任何一个进程中可以有多个线程
    • 如果希望程序中有子进程,需要自己创建进程对象(创建的进程中都自带一个线程)
  • 使用多进程

    • 创建进程对象

    • 启动进程

    • 进程阻塞

      def download(name):
          print(f'{name}开始下载:{datetime.now()}')
          time.sleep(2)
          print(f'{name}下载结束:{datetime.now()}')
      
      
      # 注意:如果想要使用多进程,必须在程序中添加这个if语句
      if __name__ == '__main__':
          # 1)创建进程对象
          p1 = Process(target=download, args=('肖生克的救赎',))
          p2 = Process(target=download, args=('惊魂记',))
          p3 = Process(target=download, args=('7号房的礼物',))
      
          # 2)启动进程
          p1.start()
          p2.start()
          p3.start()
      
          # 3)进程阻塞
          p1.join()
          p2.join()
          p3.join()
          print('下载完成!')
      

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值