• 线程


    程序:是指令的集合,是进程运行的静态描述文本
    进程:是程序的一次执行活动
    进程是资源分配的最小单位
    线程:cup调度的最小单位

    线程是属于进程的
    线程的特点:
    1.轻量级进程
    2.独立调度和分配的基本单位
    3.共享进程资源
    4.可并发执行
    为什么会有线程:
    基于网络上的服务,我们希望我们的应用在同一时刻能做更多的事情,
    并且还能共享一段数据
    线程:
    线程是进程的一部分
    一个进程必须依赖进程存在
    一个进程内至少有一个线程
    进程中默认存在线程 主线程
    也可以在一个进程中开辟多个子线程来完成更多的事情
    多个进程和多个线程都是可以利用多核的
    但是因为GIL(全局解释器锁)在cpython中不可以利用多核
    GIL全局解释器锁 是Cpython解释器中的
    
    
    关于创建线程的模块 threading thead 和Queue
    线程创建(threading模块):
    创建线程的两种方式:

    第一种:
    from threading import Thread
    def func(name):
        print('这是子线程,%s'%name)
    if __name__ == '__main__':
        t = Thread(target=func,args=('智障',))
        t.start()
        print('这是主线程')
    结果:
    这是子线程,智障
    这是主线程
    第二种:
    from threading import Thread
    class MyThread(Thread):
        def __init__(self,name):
            super().__init__()
            self.name = name
        def run(self):
            print('这是%s的子线程'%self.name)
    if __name__ == '__main__':
        t = MyThread('智障')
        t.start()
        print('主线程')
    结果:
    这是智障的子线程
    主线程
    用面向对象的方法创建线程:
    Thread中,没有__init__方法,所以必须要用super()
    必须要有run方法
    
    
    多线程和多及进程的比较:
    from multiprocessing import Process
    from threading import Thread
    import os
    def func():
        print(os.getpid())
    if __name__ == '__main__':
        p1 = Process(target=func)
        p2 = Process(target=func)
        p1.start()
        p2.start()
        p1.join()
        p2.join()
        print('主线程',os.getpid())
        t1 = Thread(target=func)
        t2 = Thread(target=func)
        t1.start()
        t2.start()
        t1.join()
        t2.join()
        print('主线程', os.getpid())
    结果:
    6072
    3080
    主线程 2440
    2440
    2440
    主线程 2440
    在主进程开启多个线程,每个线程的都跟主进程的pid一样
    在多进程中开启多个进程,每个进程的id都不一样
    内存数据的共享:
    from multiprocessing import Process
    from threading import Thread
    import os
    a = 100
    def func():
        global  a
        a = 0
    if __name__ == '__main__':
        p = Process(target=func)
        p.start()
        p.join()
        print(a)
    # 多进程中不改变a的值,说明多进程中数据不共享的
        t = Thread(target=func)
        t.start()
        t.join()
        print(a)
    #多线程改变a的值,说明线程中数据是共享的
    
    
    Thread的其他方法:
    Thread实例对象的方法:
    t.isAlive():返回线程是否活的
    t.getName():返回线程名
    t.setName():设置线程名
    threading模块提供的一些方法:
    threading.currentThread():返回当前的线程变量
    threadiing.enumerate():返回一个包含正在运行的线程的list
    正在运行指的是线程启动后,结束前不包括启动前和终止后的线程
    join方法和进程的一样
    
    
    守护线程:
    无论是线程还是进程,都遵循:守护进程/线程等主线程/进程运行完毕后进行销毁,
    需要强调的是:代码运行完毕,并不是指终止运行
    1.对进程来说:运行完毕指的是主进程代码运行完毕
    2,对线程来说:运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕
    from threading import Thread
    import time
    def func(name):
        print('%s正在吃饭'%name)
    if __name__ == '__main__':
        t1 = Thread(target=func,args=('alex',))
        t2 = Thread(target=func,args=('wusir',))
        t1.setDaemon(True)
        t1.start()
        t2.start()
        time.sleep(1)


    GIL锁:只能保证同一时刻,不可能有两个线程同时执行cpu指令
    互斥锁:保证同一时刻只能一个线程对数据进程操作,间接保证了数据的安全
    from threading import Thread,Lock
    n = 100
    def func(lock):
        global n
        with lock:
            n = n - 1
    if __name__ == '__main__':
        lock = Lock()
        for i in range(100):
            t = Thread(target=func,args=(lock,))
            t.start()
            t.join()
        print(n)
    如果不加互斥锁 数据可能会发生改变
    线程队列:
    import queue
    # import queue 和进程Queue用法一样
    queue.Queue()#先进先出
    queue.LifoQueue()#后进先出
    queue.PriorityQueue()#优先级队列需要两个参数第一个是顺序 第二个是值
    
    
    线程池(concurrent.futures):
    concurrent.futures高度封装异步调用接口
    ThreadPoolExecutor:线程池 提供异步调用
    ProcessPoolExecutor:进程池 提供异步调用
    方法:
    submit()异步提交
    map()取代for循环提交submit
    shutdown相当于进程池中的pool.close和pool.join
    result 取得结果
    add_done_callback()回调函数
    用for循环提交任务:
    import time
    from concurrent.futures import ThreadPoolExecutor
    def func(i):
        time.sleep(1)
        print('in son thread',i)
    tp = ThreadPoolExecutor(4)
    for i  in range(20):
        tp.submit(func,i)
    tp.shutdown()
    print('所有的人都执行完了')
    # 注意:
    #shutdown不能写在for循环内
    # 接收参数的位置不用写成元祖的形式了
    用map提交任务:
    import time
    from concurrent.futures import ThreadPoolExecutor
    def func(i):
        time.sleep(1)
        print('in son thread',i)
    tp = ThreadPoolExecutor(4)
    tp.map(func,range(20))
    tp.shutdown()
    print('所有的人都执行完了')
    回调函数:add_done_callback
    import time
    from concurrent.futures import ThreadPoolExecutor
    def foo(ret):
        print(ret.result())#用result()才能从未来对象中取得结果
    def func(i):
        time.sleep(0.1)
        # print('in son thread',i)
        return 'i'*i
    tp = ThreadPoolExecutor(4)
    for i  in range(20):
        ret = tp.submit(func,i)
        ret.add_done_callback(foo)
    tp.shutdown()






























































































  • 相关阅读:
    LeetCode Valid Sudoku
    接下来复习的重点
    leetcode:LRU Cache
    [leetcode] Insertion Sort List
    [QT Creator]LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 。
    [leetcode]Sort List
    李开复的七封信
    (归并排序)
    应聘面试自我介绍范文
    判断一颗二叉树是否是平衡二叉树
  • 原文地址:https://www.cnblogs.com/shicongcong0910/p/10473351.html
Copyright © 2020-2023  润新知