4.8线程和进程的使用

线程和进程的使用

  1. 线程的继承用法(class Spider(Thread))

    from threading import Thread
    
    # 继承线程的类
    class DownloadThread(Thread):
        def __init__(self, url):
            super().__init__()
            self.url = url
    	
        # 更改线程运行要执行的任务
        def run(self) -> None:
            # 确定需要在子线程中完成的任务
            print(f'{self.url}开始下载:{datetime.now()}')
            time.sleep(1)
            print(f'{self.url}下载结束:{datetime.now()}')
    
    
    t1 = DownloadThread('肖生克的救赎')
    t2 = DownloadThread('阿甘正传')
    t3 = DownloadThread('霸王别姬')
    t1.start()
    t2.start()
    t3.start()
    
  2. 多进程的队列(from multiprocessing import Queue)

    # 多进程的队列
    from multiprocessing import Queue
    
    # 使用多进程队列中需要注意:1.将队列定义全局变量   2.队列对象必须通过在子进程中调用的函数的参数传递到进程中去
    
    
    def download(name, queue: Queue):
        print(f'{name}开始下载!')
        time.sleep(1)
        print(f'{name}下载完成!')
        # return name+'数据'
        # queue.put(name+'数据')     # 往进程中添加数据
        queue.put([f'{name}10', f'{name}20'])
    
    
    if __name__ == '__main__':
        q = Queue()
        p1 = Process(target=download, args=('肖生克的救赎', q))
        p2 = Process(target=download, args=('阿甘正传', q))
        p1.start()
        p2.start()
        # p1.join()
        # p2.join()
        # 获取两个进程产生的数据
        print(q.get())      # 获取队列中的数据;如果获取的时候队列中没有数据会阻塞线程一直等,等到有数据或者超时为止
        print(q.get())
        # print(q.get())
        # print(q.get(timeout=2))
        print('=============================')
    
    
  3. 进程池(from multiprocessing import Pool)

    from multiprocessing import Pool
    
    def download(name):
        print(f'{name}开始下载')
        time.sleep(1)
        print(f'{name}下载结束')
    
    
    if __name__ == '__main__':
        # 1.创建进程池对象
        pool = Pool(maxtasksperchild=3)
    
        # 2.添加任务
        # 1)添加单个任务
        # apply - 添加同步执行
        # apply_async  - 添加异步执行
        pool.apply_async(download, args=('肖生克的救赎',))
        pool.apply_async(download, args=('触不可及',))
    
        # 2)同时添加多个任务
        # pool.map(download, ['V字仇杀队', '恐怖游轮', '林中小屋'])
    
        # 3.关闭
        pool.close()   # 停止添加任务
        # pool.apply(download, args=('摔跤吧,爸爸',))
        # 4. 等待
        pool.join()
        print('===========全部完成===========')
    
  4. 多线程的数据安全(Rlock)

    from threading import Thread, RLock
    # 加锁的原则:一个数据对应一个固定的锁对象
    # 加锁的方法:1.创建锁对象(RLock)   2.加锁    3.释放锁
    # 使用锁的注意事项:防止死锁(要保证加锁以后不管线程发生了什么,锁一定要得到释放)
    # 多个线程或者多个进程争夺同一队列的时候不会出现线程安全问题(队列本身就是线程安全)
    
    
    def sell(n):
        global num
    
        # 方法一:
        # num_lock.acquire()
        # try:
        #     t = num
        #     if n == 2:
        #         raise ValueError
        #     time.sleep(1)
        #     num = t - n
        # finally:
        #     num_lock.release()   # finally不管是否执行异常 都会解锁
    
        # 方法二
        # with 自动解锁
        with num_lock:
            t = num
            if n == 2:
                raise ValueError
            time.sleep(1)
            num = t - n
    
    
    t1 = Thread(target=sell, args=(1, ))
    t2 = Thread(target=sell, args=(2,))
    t3 = Thread(target=sell, args=(4,))
    t1.start()
    t2.start()
    t3.start()
    t1.join()
    t2.join()
    t3.join()
    print('余票:', num)
    
  5. 守护线程(daemon=True)

    # 如果一个程序有多个线程,只有在所有的线程都结束整个程序才会结束
    # 线程结束:a.线程中的任务完成(对应的函数结束)  b.出现异常
    # 守护线程:会随着主线程结束而结束的线程就是守护线程
    
    print('==============')
    
    
    def func1():
        print('子线程1开始')
        time.sleep(5)
        print('子线程1结束')
    
    
    def func2():
        print('子线程2开始')
        time.sleep(2)
        print('子线程2结束')
    
    
    # 设置守护线程
    t1 = Thread(target=func1, daemon=True)  # 给线程 赋值  daemon=True  该线程就是守护进程
    t1.start()
    t2 = Thread(target=func2)
    t2.setDaemon(True)
    t2.start()
    
    print([1, 2][10])
    time.sleep(7)
    print('主线程结束!')
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值