zoukankan      html  css  js  c++  java
  • python学习笔记(二十一)-- 进程、线程

    1、进程VS线程

    进程

      对于操作系统来说,一个任务就是一个进程。

      进程一个程序的执行实例就是一个进程,每一个进程提供执行程序所需的所有资源。

      一个进程包含一个主线程,0或者多个子线程。

    线程

            线程是执行的最小单位。

            线程不分配自己的资源,所有线程共享进程的资源,线程之间互不影响。

    线程的种类

            主线程

            子线程、

            守护线程

    2、多线程

    Python里面多线程不能利用多个CPU,它只能在一个CPU上运行。

    Python多线程使用threading模块实现

    import threading #线程模块
    import time
    
    def run(url):
        time.sleep(2)
        print(url)
        print('running...')
    def eat():
        print('吃饭')
    
    start_time = time.time()#程序开始运行时的时间戳
    
    threads = []
    
    for i in range(10):
        # 实例化一个线程,run是函数名
        t = threading.Thread(target=run,args=('http://www.baidu.com',)) # 一个参数一定加个逗号
        t.start()#启动这个线程
        threads.append(t)#把所有子进程加进threads列表
    
    # for thread in threads:
    #     thread.join()#使用join,主线程就会等待子线程执行结束再往下执行
    
    #使用上面join的方式或者while循环的方式
    # 让主线程等待子线程执行完成再执行下面的程序
    while threading.active_count() != 1: #当线程数为1,才结束循环
        pass
    
    print(threading.active_count()) #当前线程数
    
    end_time = time.time()#程序结束时的时间戳
    print('运行时间',end_time-start_time) #这个时间是主线程执行完代码的时候,不包含子线程执行时间

     多线程下载图片

    import time ,requests, threading
    from hashlib import md5
    urls = [
        'http://www.178linux.com/wp-content/uploads/2018/02/5.jpg ',
        'http://img1.imgtn.bdimg.com/it/u=1139158180,2224775217&fm=11&gp=0.jpg ',
        'http://www.linuxidc.com/upload/2019_04/19041915053582.png ',
        'http://www.veryxue.com/file/upload/201905/09/201804031578.jpg ',
        'http://5b0988e595225.cdn.sohucs.com/images/20171209/8e81dcb041a9425c823daf6b6053e03b.jpg '
    ]
    
    result = []
    
    def down_load_picture(url):
        r = requests.get(url)
        file_name = md5(r.content).hexdigest()
        with open(file_name+'.jpg','wb') as fw:
            fw.write(r.content)
            result.append(file_name)
            print('[%s]下载完成'%file_name)
    
    start_time = time.time()
    
    for url in urls:
        t = threading.Thread(target=down_load_picture,args=(url,))
        t.start()
        print(result)#在这里打印不出来,因为还没有下载完成就走到这里了
    
    
    while threading.active_count() != 1:
        pass
    
    end_time = time.time()
    run_time = end_time - start_time
    print('下载时间是%s'%run_time)

    3、守护线程

    守护线程通过setDaemon(True)设置,守护线程只守护主线程。
    当主线程运行完成,守护线程自动结束。

    import threading,time
    
    #守护线程 只能守护主线程
    print('QQ上线啦!')
    
    def conversation():
        print('聊天窗口,每天上班先聊2小时,正在聊...')
        time.sleep(20)
        print('聊完了')
    
    for i in range(10):
        t = threading.Thread(target=conversation)
        t.setDaemon(True)#设置成守护线程,主线程运行完成,守护线程自动结束
        t.start()
    
    time.sleep(1)
    print('领导来了,退出QQ')

    4、线程锁

    多个线程操作同一个数据时,有可能会出问题,这个时候就需要把操作的数据加锁,操作完成后再解锁,这样同一时间就只有一个线程可以操作这块数据。

    import threading
    
    lock = threading.Lock()#实例化一把锁
    
    sum = 0
    def add():
        global sum
        with lock: #加锁
            sum += 1
        #也可以这样加锁
        # lock.acquire()#加锁
        # sum += 1
        # lock.release()#解锁
    
    for i in range(10):
        t = threading.Thread(target=add)
        t.start()
    
    while threading.active_count()!=1:
        pass
    
    print(sum)

    5、多进程

    Python的多线程是不能利用多核CPU的,想要利用多核CPU,需要开启多进程。

    import multiprocessing,threading,random
    
    def multi_test():
        for i in range(5):
            t = threading.Thread(target=t_test)#开启线程,从随机数能看出开启了不同线程
            t.start()
    
    def t_test():
        print("这是一个线程%s"%random.randint(1,10))
    
    if __name__ == '__main__':
        for i in range(10): #循环10个进程,并调用循环开启线程的函数
            m = multiprocessing.Process(target=multi_test)
            m.start()
    
        while len(multiprocessing.active_children())!=1:
            pass
    
        print('结束')

    6、线程池

    可以使用线程池来批量启动线程,它可以自己管理线程数,最多启动设置的最大线程数,需要多少开启多少。如果线程池中线程数已满,这时有新的请求则会等待运行的线程结束后再执行新的线程。

    import threadpool
    import time
    
    urls = [
        'http://www.178linux.com/wp-content/uploads/2018/02/5.jpg ',
        'http://img1.imgtn.bdimg.com/it/u=1139158180,2224775217&fm=11&gp=0.jpg ',
        'http://www.linuxidc.com/upload/2019_04/19041915053582.png ',
        'http://www.veryxue.com/file/upload/201905/09/201804031578.jpg ',
        'http://5b0988e595225.cdn.sohucs.com/images/20171209/8e81dcb041a9425c823daf6b6053e03b.jpg '
    ]
    
    def test(url):
        time.sleep(2)
        print('test...',url)
    
    pool = threadpool.ThreadPool(2)#指定线程池大小,这是最大值,用多少会启动多少
    reqs = threadpool.makeRequests(test,urls)#第一个参数是函数名,第二个参数是所有的数据
    
    [pool.putRequest(r) for r in reqs]
    # for r in reqs:
    #     pool.putRequest(r)
    
    pool.wait()#等待子线程执行结束
    
    
    print('over!')

    7、进程池

    批量开启进程,自己对进程数进行管理,同线程池一样。

    import multiprocessing
    import os
    
    
    def worker(msg):
        print("%s开始执行,进程号为%d" % (msg, os.getpid()))
    
    
    if __name__ == '__main__':
    
        po = multiprocessing.Pool(3)  # 定义一个进程池,最大进程数3
        for i in range(0, 10):
            # Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
            # 每次循环将会用空闲出来的子进程去调用目标
            po.apply_async(func=worker, args=(i,))
        # 第一个func参数指定运行的函数,第二个args是参数,没有参数可以不写
        print("----start----")
        po.close()  # 关闭进程池,关闭后po不再接收新的请求
        po.join()  # 等待po中所有子进程执行完成,必须放在close语句之后
        print("-----end-----")
  • 相关阅读:
    PHP实现邮件的自动发送
    为PostgreSQL的表自动添加分区
    django
    django的logging模块
    job
    python 类的方法带的self理解
    java
    choice_set的理解
    django
    proxy_next_upstream带来的坑和加载sticky模块
  • 原文地址:https://www.cnblogs.com/yanyan-/p/10966079.html
Copyright © 2011-2022 走看看