zoukankan      html  css  js  c++  java
  • python--(十步代码学会线程)

    python--(十步代码学会线程)

    一.线程的创建

    Thread实例对象的方法
        # isAlive(): 返回线程是否活动的.
        # getname(): 返回线程名.
        # setName(): 设置线程名.
    
    threading模块提供的一些方法:
       # threading.currentThread(): 返回当前的线程变量。
      # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
      # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
    from threading import Thread
    from multiprocessing import Process
    
    #第一种方法
    def func(n):
        print(n)
    if __name__ == '__main__':
    
        t = Thread(target=func, args=("我是线程",))
        t.start()
        # p = Process(target=func, args=("我是进程",))
        # p.start()
        print("主进程结束.")
    
    #第二种方法
    class MyThread(Thread):
        def run(self):
            print("辉哥牛逼")
    if __name__ == "__main__":
        t = MyThread()
        t.start()
        print("主线程结束")
    线程的两种创建方式
    import time
    from threading import Thread
    from multiprocessing import Process
    def func(n):
        num = 0
        for n1 in range(n):
            num += n1
        print("num",num)
    if __name__ == '__main__':
        t_s_t = time.time()
        t_list = []
        for i in range(10):
            t = Thread(target=func, args=(10,))
            t.start()       #速度特别快
            t_list.append(t)
        [tt.join() for tt in t_list]
        t_e_t = time.time()
        t_dif_t = t_s_t - t_e_t     #获取了线程的执行时间
    
        p_s_t = time.time()
        p_list = []
        for ii in range(10):
            p = Process(target=func, args=(10,))
            p.start()   #速度非常快
            p_list.append(p)
        [pp.join() for pp in p_list]
        p_e_t = time.time() #结束时间
        p_dif_t = p_e_t - p_s_t #获取进程执行时间
    
        print('线程>>>>', t_dif_t)
        print('进程....', p_dif_t)
        print('主线程结束')
    线程和进程的效率对比

    线程的其他方法

    # 线程的一些其他方法
    # from threading import Thread
    # import threading
    # import time
    # from multiprocessing import Process
    # import os
    #
    # def work():
    #     import time
    #     time.sleep(1)
    #     print(threading.current_thread().getName()) #Thread-1
    #     print(threading.current_thread())   #Thtrad-1
    #
    # if __name__ == '__main__':
    #     #在主进程下开启线程
    #     t = Thread(target=work)
    #     t.start()
    #
    #     # print(threading.current_thread()) #主线程对象
    #     # print(threading.current_thread().getName()) #主线程名称
    #     # print(threading.current_thread().ident) #主线程ID
    #     # print(threading.get_ident()) #主线程ID
    #
    #     time.sleep(3)
    #     print(threading.enumerate()) #连同主线程在内有两个运行的线程
    #     print(threading.active_count()) #进程数
    #     print("主线程/主进程")
    View Code


    二.数据共享

    from threading import Thread
    from multiprocessing import Process
    
    num = 100
    def func():
        global num
        num = 0
    if __name__ == '__main__':
        t = Thread(target=func,)
        t.start()
        t.join()
        print(num)
    
        # p = Process(target=func,)
        # p.start()
        # p.join()
        # print(num)
    线程的数据是共享的
    mport time
    from threading import Thread,Lock
    
    #演示共享资源的时候,数据不安全的问题
    # num = 100
    # def func():
    #     global num
    #     num -= 1
    #     mid = num
    #     mid = mid - 1
    #     time.sleep(0.00001)
    #     num = mid
    # if __name__ == '__main__':
    #     t_list = []
    #     for i in range(10):
    #         t = Thread(target=func,)
    #         t.start()
    #         t_list.append(t)
    #     [tt.join() for tt in t_list]
    #     print("主进程>>>>", num)
    
    #通过锁来解决数据不安全的问题,线程模块里面引入的锁
    num = 100
    def func(t_lock):
        global num
        t_lock.acquire()
        mid = num
        mid = mid - 1
        time.sleep(0.0001)
        num = mid
        t_lock.release()
    if __name__ == '__main__':
        t_lock = Lock() #锁对象(同步锁,互斥锁)
        t_list = []
        for i in range(10):
            t = Thread(target=func,args=(t_lock,))
            t.start()
            t_list.append(t)
        [tt.join() for tt in t_list]
        print("主进程>>>>",num)
    线程共享资源不安全,加锁解决

     

    三.守护进程

    守护进程 :

    主进程代码结束程序并没有结束,并且主进程还存在,进程等待其他的子进程执行结束以后,为子进程收尸,注意一个问题:主进程的代码运行结束守护进程跟着结束,

    守护线程:

    主线程等待所有非守护线程的结束才结束,主线程的代码运行结束,还要等待非守护线程的执行完毕.这个过程中守护线程还存在

     1 import time
     2 from threading  import Thread
     3 from multiprocessing import Process
     4 def func1(n):
     5     time.sleep(5)
     6     print(n)
     7 def func2(n):
     8     time.sleep(3)
     9     print(n)
    10 if __name__ == '__main__':
    11     # p1 = Process(target=func1,args=("我是子进程1号",))
    12     #     #设置守护进程,在start之前加
    13     # p1.start()
    14     # p2 = Process(target=func2,args=("我是子进程2号",))
    15     # p2.daemon = True
    16     # p2.start()
    17     # print("子进程结束")
    线程与进程守护进程对比

    四.死锁现象

    锁(同步锁互斥锁):  保证数据安全,但是牺牲了效率,同步执行锁内的代码

    死锁现象 :   互相抢到了对方的需要的锁,导致双方相互等待,程序没法进行

    解决死锁:  递归锁,RLock   #可以多次acquire,通过一个计数器来记录被锁了多少次,只有计数器为0的时候,大 家才能继续抢锁

    import time
    from threading import Thread,Lock
    
    class MyThread(Thread):
    
        def __init__(self,lockA,lockB):
            super().__init__()
            self.lockA = lockA
            self.lockB = lockB
    
        def run(self):
            self.f1()
            self.f2()
        def f1(self):
    
            self.lockA.acquire()
            print('我拿了A锁')
    
            self.lockB.acquire()
            print('我是一个很好的客户!')
            self.lockB.release()
    
            self.lockA.release()
    
        def f2(self):
            self.lockB.acquire()
            time.sleep(0.1)
            print('我拿到了B锁')
            self.lockA.acquire()
            print('我是一名合格的技师')
            self.lockA.release()
    
            self.lockB.release()
    
    
    if __name__ == '__main__':
        lockA = Lock()
        lockB = Lock()
    
        t1 = MyThread(lockA,lockB)
        t1.start()
    
        t2 = MyThread(lockA,lockB)
        t2.start()
    
        print('我是经理')
    死锁现象
    import time
    from threading import Thread,Lock,RLock  #递归锁
    
    class MyThread(Thread):
    
        def __init__(self,lockA,lockB):
            super().__init__()
            self.lockA = lockA
            self.lockB = lockB
    
        def run(self):
            self.f1()
            self.f2()
        def f1(self):
    
            self.lockA.acquire()
            print('我拿了A锁')
    
            self.lockB.acquire()
            print('我是一个很好的客户!')
            self.lockB.release()
    
            self.lockA.release()
    
        def f2(self):
            self.lockB.acquire()
            time.sleep(0.1)
            print('我拿到了B锁')
            self.lockA.acquire()
            print('我是一名合格的技师')
            self.lockA.release()
    
            self.lockB.release()
    
    
    if __name__ == '__main__':
        # lockA = Lock()
        # lockB = Lock()
        # lockA = lockB = Lock() #不要这么写,别自己玩自己,锁自己
        lockA = lockB = RLock()
    
        t1 = MyThread(lockA,lockB)
        t1.start()
    
        t2 = MyThread(lockA,lockB)
        t2.start()
    
        print('我是经理')
    解决死锁线程方法

     

    五.信号量

    信号量:  控制同时能够进入锁内去执行代码的线程数量(进程数量),维护了一个计数器,刚开始创建信号量的时候假如设置的是4个房间,进入一次acquire就减1 ,出来一个就+1,如果计数器为0,那么其他的任务等待,这样其他的任务和正在执行的任务是一个同步的状态,而进入acquire里面去执行的那4个任务是异步执行的.

    import time
    from threading import Thread, Semaphore
    
    def func1(s):
        s.acquire()
        time.sleep(1)
        print('大宝剑!!!')
        s.release()
    
    if __name__ == '__main__':
        s = Semaphore(4)
        for i in range(10):
            t = Thread(target=func1,args=(s,))
            t.start()
    信号量

    六.事件

    # # 事件
    # from threading import Thread,Event
    # e = Event() #e的状态有两种,False Ture,当事件对象的状态为False的时候,wait的位置会阻塞
    #
    # e.set() #将事件对象的状态改为Ture
    # e.clear() #将事件对象的状态改为False
    # print("在这里等待")
    # e.wait() #阻塞
    # print("还没好")
    View Code

    七.队列

    mport queue
    
    #先进先出 FIFO
    # q=queue.Queue()
    # q.put('first')
    # q.put('second')
    # q.put('third')
    # # q.put_nowait() #没有数据就报错,可以通过try来搞
    # print(q.get())
    # print(q.get())
    # print(q.get())
    # # q.get_nowait() #没有数据就报错,可以通过try来搞
    
    # '''
    # first
    # second
    # third
    # '''
    
    # 先进后出
    # import queue
    
    # q = queue.LifoQueue() #队列类似于栈,先进后出的顺序
    # q.put('first')
    # q.put('second')
    # q.put('third')
    # q.put_nowait()
    
    # print(q.get())
    # print(q.get())
    # print(q.get())
    # # q.get_nowait()    #没有数据就报错
    
    # '''
    # third
    # second
    # first
    # '''
    
    
    # # 优先级队列
    # import queue
    # q = queue.PriorityQueue()
    # #put进入一个元祖,元祖的第一个元素是优先级(通常是数字,也可以是非数字之间的比较,数字越小优先级越高
    # q.put((-10,"a"))
    # q.put((-5,"a")) #负数也可以
    #
    # # q.put((20,'b')) #如果第一个参数数字的优先级一样,那么按照后面的字符串acsii来排序
    # # q.put((20,'c'))
    #
    # # q.put((20,{'a':11})) #TypeError: unorderable types: dict() < dict() 不能是字典
    # # q.put((20,('w',1)))  #优先级相同的两个数据,他们后面的值必须是相同的数据类型才能比较,可以是元祖,也是通过元素的ascii码顺序来排序
    #
    # print(q.get())
    # print(q.get())
    # """结果:数字越小优先级越高,优先级高的优先出队"""
    View Code

    八.线程池

    concurrent.futures模块提供了高度封装的异步调用接口
    ThreadPoolExecutor:线程池,提供异步调用
    ProcessPoolExecutor: 进程池,提供异步调用
    Both implement the same interface, which is defined by the abstract Executor class.
    
    #2 基本方法
    #submit(fn, *args, **kwargs)
    异步提交任务
    
    #map(func, *iterables, timeout=None, chunksize=1) 
    取代for循环submit的操作
    
    #shutdown(wait=True) 
    相当于进程池的pool.close()+pool.join()操作
    wait=True,等待池内所有任务执行完毕回收完资源后才继续
    wait=False,立即返回,并不会等待池内的任务执行完毕
    但不管wait参数为何值,整个程序都会等到所有任务执行完毕
    submit和map必须在shutdown之前
    
    #result(timeout=None)
    取得结果
    
    #add_done_callback(fn)
    回调函数
    # 线程池
    # import time
    # from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    # #ProcessPoolExecutor 进程池
    # from threading import current_thread
    #
    # def func(n):
    #     time.sleep(1)
    #     # print(n,current_thread().ident)
    #     return n**2
    # if __name__ == '__main__':
    #     t_p = ThreadPoolExecutor(max_workers = 4)
    #     map_res = t_p.map(func,range(10))   #异步执行的,map自带join功能
    #     print(map_res)
    #     print([i for i in map_res])
    View Code

    线程池的一些其他方法

    # 线程池的一些其他方法
    # import time
    # from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    # from threading import current_thread
    # def func(n):
    #     time.sleep(1)
    #     #print(n,current_thread().ident)
    #     return n**2
    # def func2(n):
    #     print(n)
    # if __name__ == '__main__':
    #     t_p = ThreadPoolExecutor(max_workers=4)
    #     t_p_list = []
    #     for i in range(10):
    #         res_obj = t_p.submit(func, i) #异步提交了这10个任务
    #         # res_obj.result()    #他和get一样
    #         t_p_list.append(res_obj)
    #     t_p.shutdown()  #close + join 等待全部完成之后关闭子线程,防止后面数据进入
    #     # print('t_res_list',t_p_list)
    #     for e_res in t_p_list:
    #         print(e_res.result())
    View Code

    九.回调函数

    rom concurrent.futures import ThreadPoolExecutor
    from threading import current_thread
    
    def func(n):
        time.sleep(1)
        print(n**2)
        # print(n,current_thread().getName())
        # return n**2
    def func2(n):
        # print("current_thread>>>>",current_thread().getName())
        print(n.result())  #result() 相当于 get()
    if __name__ == '__main__':
        t_p = ThreadPoolExecutor(max_workers=1)
        for i in range(3):
            t_p.submit(func, i).add_done_callback(func2)
    
        print('主进程结束')
    View Code

    十.GIL锁

    #保证数据安全,锁的是整个线程,每次只能有一个线程使用cpu,是CPython解释器的特性
      
      
     

    
    
    
    
    
  • 相关阅读:
    数组练习1
    学习进度04
    求一个数组的最大子数组之和02
    求一个数组的最大子数组之和01
    学习进度03
    四则运算的功能添加版02
    第二周学习进度
    Right-BICEP 测试四则运算程序
    实现四则运算的功能添加版01
    本周实验PSP0 过程文档
  • 原文地址:https://www.cnblogs.com/konghui/p/9857611.html
Copyright © 2011-2022 走看看