2018-08-08 day18 多线程

进程和线程

1.什么是进程

  • 进程是指在系统中正在运行的一个应用程序
  • 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内

2.什么是线程

  • 一个进程想要执行任务,必须有线程(每个进程至少要有1条线程)
  • 一个进程(程序)的所有任务都在线程中执行

3.什么是多线程

  • 1个进程中可以开启多条线程,每条线程可以并行执行不同的任务
  • 多线程技术可以提高程序的执行效率

4.多线程的原理

  • 同一个时间,CPU只能处理一条线程,只有1条线程在执行
  • 多线程并发执行,其实是cpu快速的在多条线程之间调度
  • 如果CPU调度线程的事件足够快,就造成了多线程并发执行的假象

耗时操作

1.耗时操作放到主线程中的问题

  • 耗时操作放到主线程中会阻塞线程
  • 多个耗时操作都放到一个线程中执行,最终执行时间是多个耗时操作时间和

2.怎么解决

  • 使用多线程(创建多个线程)

多线程技术

  • python内置的threading模块,可以支持多线程

  • 所有的进程默认都有一个线程(一般叫这个线程为主线程),其他的线程叫子线

  • 如果想要在进程中添加其他的线程,就创建线程对象

import threading
import time


def download(file):
    print('开始下载', file)
    time.sleep(3)
    print(file, '下载结束')


if __name__ == '__main__':
    print('aaaa')
    # 1.创建线程对象
    
    target:需要在子线程中执行的函数
    args:调用函数的实参列表(参数类型必须是列表)
    
    t1 = threading.Thread(target=download, args=['爱情公寓'])
    # 2.在子线程中执行任务
    t1.start()
    t2 = threading.Thread(target=download, args=['allalala'])
    t2.start()
    print('66666666666')
    time.sleep(5)
  • 方式2:写一个自己的线程类
  1. 写一个类,继承Thread类
  2. 重写run方法,在里面规定需要在子线程中执行的任务
  3. 在子线程中执行的任务对应的功能,如果需要参数,通过对象属性来传值

传值使用对象属性来传值

from threading import Thread
from requests import request
import os
import re


# 下载数据
class DownloadThread(Thread):
    '''下载类'''

    def __init__(self, file):
        super().__init__()
        self.file = file

    def run(self):
        '''run方法'''
        '''
        写在这个方法的内容就是在子线程中执行的内容
        这个方法不要直接调用
        '''
        print('开始下载')
        suffix = re.search(r'[%\\]\w+\.\w+$', self.file).group()
        response = request('GET', self.file)
        data = response.content
        with open('./day02-多线程/' + suffix, 'wb') as f:
            f.write(data)
        print('下载完成....')


if __name__ == '__main__':
    print(os.getcwd())
    d1 = DownloadThread(
        'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1533720058151&di=766b5c97653351e805c85881ecaa57d0&imgtype=0&src=http%3A%2F%2Fx.itunes123.com%2Fuploadfiles%2Fb2ab55461e6dc7a82895c7425fc89017.jpg'
    )
    # 通过start间接调用run方法,run方法中的任务在子线程中执行
    d1.start()
    # 直接调用run方法,run方法在当前线程中执行
    print('哇哈哈哈哈哈哈')

多线程的应用

import socket
from threading import Thread


class MsgThread(Thread):
    '''在子线程中处理不同的客户端会话'''

    def __init__(self, conver: socket.socket, addr):
        # 形参接受时,参数后面加:进行类型说明
        # 注意只是说明类型而不是转换类型
        super().__init__()
        self.conver = conver
        self.addr = addr

    def run(self):
        while True:
            self.conver.send('哇哈哈哈'.encode())
            print(self.addr, self.conver.recv(1024).decode(encoding='utf-8'))


if __name__ == '__main__':
    server = socket.socket()
    server.bind(('10.7.181.92', 8080))
    server.listen(5)
    while True:
        conver, addr = server.accept()
        c = MsgThread(conver, addr)
        c.start()
        # while True:
        # conver.send('666'.encode())
        # print(conver.recv(1024).decode(encoding='utf-8'))

join方法

  • 获取当前线程
  • 主线程:MainThread
  • 子线程:Thread-数字
currentThread()
  • 如果一个任务想要在另一个子线程结束后再执行,就用这个子线程对象调用join
  • 所以join也会阻塞线程,阻塞到子线程任务执行完成为止
from threading import Thread, currentThread
from random import randint
import time


class Download(Thread):
    def __init__(self, file):
        super().__init__()  # 必须调用,否则当前这个类对象就不是线程
        self.file = file

    def run(self):
        print('开始下载', self.file)
        time.sleep(randint(3, 7))
        print(currentThread())
        print('下载完成', self.file)


if __name__ == '__main__':
    # time.time():获取当前的时间戳
    start_time = time.time()
    t1 = Download('狗屎')
    t1.start()

    t2 = Download('红糖')
    t2.start()
    print('.............')
    # 获取当前线程
    '''
    主线程:MainThread
    子线程:Thread-数字
    '''
    print(currentThread())
    # 如果一个任务想要在另一个子线程结束后再执行,就用这个子线程对象调用join
    # 所以join也会阻塞线程,阻塞到子线程任务执行完成为止
    t1.join()
    end_time = time.time()
    print('耗时%.2f' % (end_time - start_time))
    t2.join()
    end_time = time.time()
    print('总共耗时%.2f' % (end_time - start_time))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容