美文网首页
2018-08-08 day18 多线程

2018-08-08 day18 多线程

作者: Kris_Shin | 来源:发表于2018-08-08 18:39 被阅读0次

    进程和线程

    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))
    

    相关文章

      网友评论

          本文标题:2018-08-08 day18 多线程

          本文链接:https://www.haomeiwen.com/subject/kjgxbftx.html