zoukankan      html  css  js  c++  java
  • 并发编程之多线程

    周三 多线程 (非常重要)() 多线程互斥锁 (重要)() 守护线程 (一般)() 信号量 一般() 生产者消费者+守护进程 一般(**)

    周四 GIL锁 线程池 进程池

    周五 协程

    多线程

    多线程也是用于提高程序的效率
    
    多进程
        核心是多道技术       
        本质上就是切换保存状态
        当程序IO操作较多 可以提高程序效率
        
    多线程
    什么是线程
        程序的执行线路
        相当于一条流水线,其包含了程序的具体执行步骤
        如果我们把操作系统比作一个工厂,进程就是车间,线程就是流水线
        
    线程和进程的关系
        进程中包含了运行该程序所需要的所有资源
        *进程是一个资源单位,线程是cpu的最小执行单位*
        每一个进程一旦被创建,就默认开启了一条线程,我们把这个线程称之为主线程
        一个进程可以包含多个线程
        进程包含线程,而 线程依赖进程
        
    为什么使用线程
        是为了提高程序效率
        为何不用多进程提高效率? 是因为进程对操作系统的资源耗费非常高
            
    线程是如何提高效率的?
        可以使cpu在一个进程内切换,从而提高cpu的占用率
        
        
    什么情况下应该开启多线程
        当程序中遇到IO操作的时候
    什么情况下不应该开启多线程
        当程序中是纯计算任务的时候,也无法提高效率
        
    进程和线程的区别
        1.进程对于操作系统的资源耗费非常高,而线程相反非常低(比进程低10_100倍)
        2.在同一个进程中,多个线程之间的资源是共享的
            
    如何使用    
        两种开启线程的方式
        1.实例化Tread类
        2.继承Tread类 覆盖run方法
    
    # 开启线程的第一种方式
    from threading import Thread
    from multiprocessing import Process
    
    def task():
        print("threading running!")
    
    t1 = Thread(target=task)
    t1.start()
    print("over")
    
    
    
    # 第二种方式
    class MyThread(Thread):
        def run(self):
            print("子线程 running....")
    MyThread().start()
    print("over2")

    对比进程启动时间

    from threading import Thread      
    import time                       
                                 
    # class MyThread(Thread):         
    #     def run(self):              
    #         # print("子进程run.....")  
    #        pass                     
    #                                 
    # if __name__ == '__main__':      
    #                                 
    #     ts = []                     
    #     start = time.time()         
    #     for i in range(100):        
    #                                 
    #         t1 = MyThread()         
    #         t1.start()              
    #         ts.append(t1)           
    #                                 
    #     for t in ts:                
    #         t.join()                
    #                                 
    #     print(time.time()-start)    
    #     print("over")               
    
    
    from multiprocessing import Process                   
    import time                                           
    def task():                                           
        pass                                              
    
        # print("子进程run...")                              
    
    if __name__ == '__main__':                            
        p   s = []                                           
        start = time.time()                               
        for i in range(100):                              
            p = Process(target=task)                      
    
            p.start()                                     
            ps.append(p)                                  
    
        for p in ps:                                      
            p.join()                                      
    
        print(time.time()-start)                          
        print("over")

    进程间资源共享

    from threading import Thread          
    a = 100                               
                                          
    def task():                           
        global a                          
        a = 0                             
                                          
    if __name__ == '__main__':            
        t = Thread(target=task)           
        t.start()                         
                                          
        print(a)

    守护线程

    守护线程会在所有非守护线程结束后结束
        如果把皇后设置为守护线程,那么皇后线程会在太子和皇帝都死亡后死亡
    
    进程 守护进程会在被守护进程死亡跟着死亡
    同一个进程 可以有多个守护线程
    
    """
        守护线程
        守护线程会在所有非守护线程结束后结束
            三个线程 分贝 皇帝 太子 和皇后
            如果把皇后设置为守护线程 那么皇后线程会在 太子和皇帝都死亡后死亡
        当所有非线程结束后 守护线程也跟着结束了
    
    
        进程 守护进程会在被守护进程死亡跟着死亡
        同一个进程 可以有多个守护线程
    
    """
    
    from threading import Thread
    
    #
    # import time
    #
    # def task():
    #     print("sub thread run....")
    #     time.sleep(3)
    #     print("sub thread over....")
    #
    # t = Thread(target=task)
    # t.setDaemon(True)
    # t.start()
    #
    #
    # t = Thread(target=task)
    # t.setDaemon(True)
    # t.start()
    #
    # print("over!")
    from threading import Thread
    import time
    
    def task():
        print("子线程运行。。。")
        time.sleep(1)
        print("子线程结束。。。")
    t = Thread(target=task)
    t.setDaemon(True)
    
    t.start()
    # time.sleep(0.1)
    print("over")

    线程常用方法

    from threading import Thread,current_thread,enumerate,active_count
    
    import os
    
    def task():
        print("running..")
        # print(os.getpid())
        # print(current_thread())
        print(active_count())
    
    t1 = Thread(target=task)
    t1.start()
    # print(t1.is_alive())
    # print(t1.isAlive())
    # print(t1.getName())
    
    # 获取所有线程对象列表
    print(enumerate())
    # 获取当前线程对象
    print(current_thread())
    # 获取当前正在运行的线程个数
    print(active_count())
    
    # t2 = Thread(target=task)
    # t2.start()

    什么时候用锁

    当多个进程或多个线程需要同时修改同一份数据时,可以加锁
    
    import time
    from threading import Thread,Lock
    
    lock =Lock()
    
    a = 100
    
    def task():
        lock.acquire()
        global a
        temp = a - 1
        time.sleep(0.01)
        a = temp
        lock.release()
    
    ts = []
    for i in range(100):
        t = Thread(target=task)
        t.start()
        ts.append(t)
    
    for t in ts:
        t.join()
    
    
    print(a)

    信号量

    其实也是一种锁,特点是可以设置一个数据可以被几个线程(进程)共享
    
    与普通锁的区别
        普通锁一旦加锁,则意味着,这个数据在同一时间只能被一个线程使用
        信号量可以让这个数据在同一时间被多个线程使用
    使用场景,可以限制一个数据被同时访问的次数,保证程序正常运行
        
    
    from threading import Semaphore,Thread,current_thread
    import time,random
    
    sem = Semaphore(3)
    
    def task():
        sem.acquire()
        print("%s run..." % current_thread())
        time.sleep(3)
        sem.release()
    
    
    for i in range(10):
        t = Thread(target=task)
        t.start()

    守护进程在生产者消费者模型中的使用

    """
        生产者与消费者模型
    
    
        吃热狗 与  做热狗
    """
    import time,random
    from multiprocessing import Process,JoinableQueue
    def eat_hotdog(name,q):
        while True:
            res = q.get()
            print("%s吃了%s" % (name,res))
            time.sleep(random.randint(1,2))
            q.task_done() #记录已经被处理的数据的数量
    
    def make_hotdog(name,q):
        for i in range(1,6):
            time.sleep(random.randint(1, 2))
            print("%s生产了第%s个热狗" % (name,i))
            res = "%s的%s个热狗" % (name,i)
            q.put(res)
        # q.put(None)
    
    if __name__ == '__main__':
        q = JoinableQueue()
        #生产者1
        c1 = Process(target=make_hotdog,args=("万达热狗店",q))
        c1.start()
    
        #生产者2
        c2 = Process(target=make_hotdog, args=("老男孩热狗店", q))
        c2.start()
    
        # 消费者
        p2 = Process(target=eat_hotdog,args=("思聪",q))
    
        p2.start()
    
    
        # 首先保证生产者全部产完成
        c1.join()
        c2.join()
    
        # 保证队列中的数据全部被处理了
        q.join() # 明确生产方已经不会再生成数据了
  • 相关阅读:
    Struts2 HelloWorld_1
    Java Web JavaMail 邮件发送
    Struts2 ActionWildcard(通配符配置)约定优于配置
    Struts2 Action
    Struts2 struts2简介
    Struts2 ActionMethod DMI(动态方法调用)
    Java Web Servlet过滤器
    com学习笔记(2)基本的com接口QueryInterface的实现
    com学习笔记(4)动态链接
    silverlight Visifire图表转图片偷天换日的做法
  • 原文地址:https://www.cnblogs.com/shanau2/p/10209270.html
Copyright © 2011-2022 走看看