• python并发之多线程


    一开启线程的两种方式

    from threading import Thread
    import time
    def haha(name):
        time.sleep(2)
        print('%s 你大爷......'%name)
    
    if __name__ == '__main__':
        t=Thread(target=haha,args=('一根',))
        t.start()
        t.join()
        print('')
    from threading import Thread
    import time
    def jiji(eat):
        time.sleep(1)
        print('%s 富贵,你吃了什么???'%eat)
    if __name__ == '__main__':
        time.sleep(2)
        t=Thread(target=jiji,args=('',))
    
        t.start()
        print('')
    方式一
    from threading import Thread
    import time
    class hh(Thread):
        def __init__(self,name):
            super().__init__()
            self.name=name
    
        def play(self):
            time.sleep(2)
            print('%s basket-ball......'%self.name)
    if __name__ == '__main__':
        t=hh('王浩')
        t.start()
        print('主线程')
    方式二

    二在一个进程下开启多个线程与在一个进程下开启多个子进程的区别

    from multiprocessing import Process
    from threading import Thread
    import os
    
    def work():
        print('hello')
    
    if __name__ == '__main__':
        #在主线程下来气进程
        t=Thread(target=work)
        t.start()
        print('主线程/主进程')
    
        '''
        打印结果:
        hello
        主线程/主进程
        '''
    
        #在主进程下开启子进程
        t=Process(target=work)
        t.start()
        print('主线程/主进程')
    
        '''
        打印结果:
        主线程/主进程
        hello
        '''
    子线程比子进程打印的快
    from multiprocessing import Process
    from threading import Thread
    import os
    def work():
        print('hello',os.getpid())
    if __name__ == '__main__':
    
        #part1:在主进程下开启多个线程,每个线程都和主进程的pid一样
        t1=Thread(target=work)
        t2=Thread(target=work)
        t1.start()
        t2.start()
        print('主线程/主进程pid',os.getpid())
    
        #part2:开启多个进程,每个进程都有着不同的pid
        p1=Process(target=work)
        p2=Process(target=work)
        p1.start()
        p2.start()
        print('主线程/主进程pid',os.getpid())
    pid
    from threading import Thread
    from multiprocessing import Process
    import os
    def work():
        global n
        n=0
    
    if __name__ == '__main__':
        n=100
        p=Process(target=work)
        p.start()
        p.join()
        print('',n)  #毫无疑问子进程p已经将自己的全局的n改成了0,当改的仅仅是他自己的,父进程n任然是100
    
        n=1
        t=Thread(target=work)
        t.start()
        t.join()
        print('',n)#查看结果为0,因为同一进程内的线程之间共享进程内的数据
    同一进程内的线程共享该进程的数据

    三练习

    import multiprocessing
    import threading
    
    import socket
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.bind(('127.0.0.1',8080))
    s.listen(5)
    
    def action(conn):
        while True:
            data=conn.recv(1024)
            print(data)
            conn.send(data.upper())
    
    if __name__ == '__main__':
    
        while True:
            conn,addr=s.accept()
    
    
            p=threading.Thread(target=action,args=(conn,))
            p.start()
    
    多线程并发的socket服务端
    多线程并发的socket服务端
    import socket
    
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.connect(('127.0.0.1',8080))
    
    while True:
        msg=input('>>: ').strip()
        if not msg:continue
    
        s.send(msg.encode('utf-8'))
        data=s.recv(1024)
        print(data)
    客户端

    2三个任务,一个接收用户输入,一个将用户输入的内容格式化成大写,一个将格式化后的结果存入文件

    from threading import Thread
    msg_l=[]
    format_l=[]
    def talk():
        while True:
            msg=input('>>: ').strip()
            if not msg:continue
            msg_l.append(msg)
    
    def format_msg():
        while True:
            if msg_l:
                res=msg_l.pop()
                format_l.append(res.upper())
    
    def save():
        while True:
            if format_l:
                with open('db.txt','a',encoding='utf-8') as f:
                    res=format_l.pop()
                    f.write('%s
    ' %res)
    
    if __name__ == '__main__':
        t1=Thread(target=talk)
        t2=Thread(target=format_msg)
        t3=Thread(target=save)
        t1.start()
        t2.start()
        t3.start()
    View Code

    四线性相关其他知识

    Thread实例对象的方法
     isAlive(): 返回线程是否活动的。
     getName(): 返回线程名。
     setName(): 设置线程名。
    
    threading模块提供的一些方法:
    threading.currentThread(): 返回当前的线程变量。
    threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前
    终止后的线程。
    hreading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
    from threading import Thread
    import threading
    from multiprocessing import Process
    import os
    
    def work():
        import time
        time.sleep(3)
        print(threading.current_thread().getName())
    
    
    if __name__ == '__main__':
        #在主进程下开启线程
        t=Thread(target=work)
        t.start()
    
        print(threading.current_thread().getName())
        print(threading.current_thread()) #主线程
        print(threading.enumerate()) #连同主线程在内有两个运行的线程
        print(threading.active_count())
        print('主线程/主进程')
    
        '''
        打印结果:
        MainThread
        <_MainThread(MainThread, started 140735268892672)>
        [<_MainThread(MainThread, started 140735268892672)>, <Thread(Thread-1, started 123145307557888)>]
        主线程/主进程
        Thread-1
        '''
    View Code

    主线程等待子线程结束

    from threading import Thread
    import time
    def sayhi(name):
        time.sleep(2)
        print('%s say hello' %name)
    
    if __name__ == '__main__':
        t=Thread(target=sayhi,args=('egon',))
        t.start()
        t.join()
        print('主线程')
        print(t.is_alive())
        '''
        egon say hello
        主线程
        False
        '''
    View Code

    五守护线程

    无论进程还是线程,都是守护主进程运行结束后自动销毁,那么运行接受又是在那种情况下的呢?

    1主进程在其代码结束后就算运行结束了(守护进程就会被销毁),主进程就会等待非守护的子进程运行结束后回收其资源,才会结束。

    2主线程在其他非守护进程完毕后才算完(守护进程被销毁),主线程结束意味着进程结束,进程整体资源被回收,所以主线程必须在其他线程结束后才结束

    from threading import Thread
    import time
    def sayhi(name):
        time.sleep(2)
        print('%s say hello' %name)
    
    if __name__ == '__main__':
        t=Thread(target=sayhi,args=('egon',))
        t.setDaemon(True) #必须在t.start()之前设置
        t.start()
    
        print('主线程')
        print(t.is_alive())
        '''
        主线程
        True
        '''
    View Code
    from threading import Thread
    import time
    def foo():
        print(123)
        time.sleep(1)
        print("end123")
    
    def bar():
        print(456)
        time.sleep(3)
        print("end456")
    
    
    t1=Thread(target=foo)
    t2=Thread(target=bar)
    
    t1.daemon=True
    t1.start()
    t2.start()
    print("main-------")
    
    迷惑人的例子
    有点挖坑的意思哦

    六 Python GIL(Global Interpreter Lock)

    定义:

    在CPython中,全局解释器锁是一个互斥锁,它可以防止多个对象的出现。

    本地线程同时执行Python的一组语言。这个锁是主要的

    因为CPython的内存管理不是线程安全的。(然而,由于吉尔

    存在,其他的特性已经发展到依赖于它所执行的保证。)

    结论:在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势。

    1. 多cpu,意味着可以有多个核并行完成计算,所以多核提升的是计算性能

    2. 每个cpu一旦遇到I/O阻塞,仍然需要等待,所以多核对I/O操作没什么用处

    结论:

      对计算来说,cpu越多越好,但是对于I/O来说,再多的cpu也没用

      当然对运行一个程序来说,随着cpu的增多执行效率肯定会有所提高(不管提高幅度多大,总会有所提高),这是因为一个程序基本上不会是纯计算或者纯I/O,所以我们只能相对的去看一个程序到底是计算密集型还是I/O密集型。

    #分析:
    我们有四个任务需要处理,处理方式肯定是要玩出并发的效果,解决方案可以是:
    方案一:开启四个进程
    方案二:一个进程下,开启四个线程
    
    #单核情况下,分析结果: 
      如果四个任务是计算密集型,没有多核来并行计算,方案一徒增了创建进程的开销,方案二胜
      如果四个任务是I/O密集型,方案一创建进程的开销大,且进程的切换速度远不如线程,方案二胜
    
    #多核情况下,分析结果:
      如果四个任务是计算密集型,多核意味着并行计算,在python中一个进程中同一时刻只有一个线程执行用不上多核,方案一胜
      如果四个任务是I/O密集型,再多的核也解决不了I/O问题,方案二胜
    
     
    #结论:现在的计算机基本上都是多核,python对于计算密集型的任务开多线程的效率并不能带来多大性能上的提升,甚至不如串行(没有大量切换),但是,对于IO密集型的任务效率还是有显著提升的。
    

      

    from multiprocessing import Process
    from threading import Thread
    import os,time
    def work():
        res=0
        for i in range(100000000):
            res*=i
    
    
    if __name__ == '__main__':
        l=[]
        print(os.cpu_count()) #本机为4核
        start=time.time()
        for i in range(4):
            p=Process(target=work) #耗时5s多
            p=Thread(target=work) #耗时18s多
            l.append(p)
            p.start()
        for p in l:
            p.join()
        stop=time.time()
        print('run time is %s' %(stop-start))
    计算密集型:多进程效率高
    from multiprocessing import Process
    from threading import Thread
    import threading
    import os,time
    def work():
        time.sleep(2)
        print('===>')
    
    if __name__ == '__main__':
        l=[]
        print(os.cpu_count()) #本机为4核
        start=time.time()
        for i in range(400):
            # p=Process(target=work) #耗时12s多,大部分时间耗费在创建进程上
            p=Thread(target=work) #耗时2s多
            l.append(p)
            p.start()
        for p in l:
            p.join()
        stop=time.time()
        print('run time is %s' %(stop-start))
    I/O密集型:多线程效率高

    应用:

    多线程用于IO密集型,如socket,爬虫,web
    多进程用于计算密集型,如金融分析

     

     

      

  • 相关阅读:
    使用uploadify上传图片时返回“Cannot read property 'queueData' of undefined”
    用户在网站注册,网站通过微信发送验证码,这个操作是怎么实现的?
    Javascript Array和String的互转换。
    JS判断一个数组中是否有重复值的三种方法
    监控聚币网行情 并实时发送到微信
    聚币网API使用教程 demo
    sourceTree安装与使用
    SourceTree 的初次使用的两个小问题
    解决oracle语句中 含数字的字符串按数字排序问题
    使用git pull文件时和本地文件冲突怎么办
  • 原文地址:https://www.cnblogs.com/wanghaohao/p/7449687.html
Copyright © 2020-2023  润新知