• 十一、多线程


    一、多线程基础 

    进程拥有资源(内存等),线程不拥有资源,共享进程的资源

    同属于一个进程中的线程可以共享CPU分配的全部资源

    多个线程的切换速度比多个进程快,消耗的资源也少。

    多个线程可以并行地在多核CPU中执行。

    进程是系统资源分配的基本单元

    线程是CPU 调度和分配的基本单位

    线程不拥有系统资源,但可以访问隶属于进程的资源

    一个进程默认有一个线程

    线程是由操作系统调用的

    协程是由用户调用的 

    """
    线程类:threading.Thread
    线程任务:target
    线程任务的参数:args
    线程名:name
    该举例1个进程,2个线程
    """ import threading import time def music(user): for i in range(5): time.sleep(1) print(f'{user}正在听音乐{i}') print(f'{threading.current_thread().name}正在运行') def lol(user): for i in range(5): time.sleep(1) print(f'{user}正在玩LOL{i}') print(f'{threading.current_thread().name}正在运行') def main(): # 创建2个线程 t1 = threading.Thread(target=music, args=('小样儿',), name='线程1') t2 = threading.Thread(target=lol, kwargs={'user': '小样儿'}, name='线程2') # 启动线程 t1.start() t2.start() t1.join() # 阻塞 t2.join() print("程序结束!") if __name__ == '__main__': main()

    二、多线程共享全局变量 

    import threading
    
    n = 100
    
    def work1():
        global n
        for i in range(1000):
            n += 1
    
    def work2():
        global n
        for i in range(1000):
            n += 1
    
    if __name__ == '__main__':
        t1 = threading.Thread(target=work1)
        t2 = threading.Thread(target=work2)
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        print(f'n:{n}')  # 2100

    三、线程锁

    根据以上例子,当线程并发次数多时,如range(100000)等,就会出错

    因此需要线程锁,确保每次

    import threading
    
    n = 200000
    lock = threading.Lock()
    
    def work():
        global n
        for i in range(100000):
            lock.acquire()  # 关门上锁
            # with lock:  # 防止同时修改n
            n -= 1
            lock.release()  # 解锁
    
    if __name__ == '__main__':
        t1 = threading.Thread(target=work)
        t2 = threading.Thread(target=work)
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        print(f'n:{n}')

     四、自定义线程类

    import threading
    import time
    
    class MyThread(threading.Thread):
        def __init__(self, user):
            super(MyThread, self).__init__()
            self.user = user
    
        def run(self):
            """线程启动的时候会调用此方法"""
            for i in range(5):
                time.sleep(1)
                print(f'{self.user}正在听音乐...')
    
    if __name__ == '__main__':
        t = MyThread(user='小样儿')
        t.start()

    五、线程池

    import time
    from concurrent.futures import ThreadPoolExecutor
    
    def work(result):
        time.sleep(1)
        print("Hello!")
        return result
    
    def main():
        thread_executor = ThreadPoolExecutor(max_workers=5)
        future = thread_executor.submit(work, "完成")
        print(future.done())
        time.sleep(2)
        print(future.done())
        print(future.result())
    
    if __name__ == '__main__':
        main()
    
    '''
    False
    Hello!
    True
    完成
    '''

    参考资料转自:https://www.cnblogs.com/hoojjack/p/10846010.html

    六、第三方线程池(threadpool)

    安装:pip  install threadpool

    import time
    
    import threadpool
    
    def hi(s):
        print(f"hi,{s}
    ")
        time.sleep(2)
    
    def main():
        start_time = time.time()
        thread_pool = threadpool.ThreadPool(2)
        reqs = threadpool.makeRequests(hi, ['a', 'b', 'c'])
        for req in reqs:
            thread_pool.putRequest(req)
        thread_pool.wait()  # 等待线程池中的所有线程执行完毕
        end_time = time.time()
        print(f'总共花费时间为:{end_time - start_time}')
    
    
    if __name__ == '__main__':
        main()
    
    '''
    hi,a
    hi,b
    hi,c
    总共花费时间为:4.006930828094482
    '''

    七、GIL锁

    GIL: 中文全局“解释器”锁。锁的是谁利用CPU,锁不住代码

    线程占用CPU: 无论是多核CPU,还是多CPU,同一间时间,只有一个线程在使用CPU

    CPU密集型场景,不要用多线程,用了反而慢,原因是Python不能利用多核(GIL决定的)

    IO密集型场景,使用多线程可以节省时间。因为IO不占用CPU,GIL锁影响不大。

  • 相关阅读:
    开源.net 混淆器ConfuserEx介绍
    k8s删除namespace失败,状态Terminating解决方案
    java get all threadlocal from thread
    mysql查看索引的大小
    InnoDB一定会在索引中加上主键吗?
    全链路追踪traceId,ThreadLocal与ExecutorService
    redis 批量删除keys
    shell逐行读取excel并执行sql
    Is it possible to create @Around Aspect for feign.Client
    Spring Boot后台启动不打印nohup.out
  • 原文地址:https://www.cnblogs.com/zhangjx2457/p/14129970.html
Copyright © 2020-2023  润新知