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

    并发编程:多进程

    进程创建的两种方式

    #第一种
    from multiprocessing import Process
    import time
    def func(name):(
        print(f'{name}子进程开始')
        time.sleep(1)
        print(f'{name}子进程结束')
    if __name__=='__main__':
        times=time.time()
        x = Process(target=func,args('宋',))   #里面一定要放元组
        x.start()              #启动进程,并调用该子进程中的x.run()
        time.sleep(1)      #x.run()调用target制定的函数,启动进程运行的方法
        print('主进程启动')
        print(f'{time.time()-times}')
    #第二种
    from multiprocessing import Process
    import time
    class A(Process):    #父类一定是Process
        def __init__(self,name):
        self.name=name
        super().__init__()
    	def run(self):       #一定要有run方法!!!!!!
        	print(f'{self.name}子进程开始')
        	time.sleep(1)
        	print(f'{self.name}子进程结束')
    if __name__=='__main__':
        times=time.time()
        x=A('宋',)
        x.start()          #只是想操作系统发憷一个开辟子进程的信号,执行下一行,信号接收到了,会在内存总开辟一个进程空间,然后再讲主进程所有数据copy加载到子进程,然后在调用CPU去执行,开辟子进程开销是很大的
        time.sleep(1)
       	print(f'{time.time()-times}主进程开启')
        #所以永远会先执行主进程的代码
        
        
    x.terminate()  #强制终止进程x 不会进行任何清理操作 
    x.is_alive()   #判断进程是不是还活着
    x.join()   #主进程等待执行完子进程以后再执行主进程
    x.daemon() #默认值为Flase 代表x为后台运行的守护进程
    x.name  #查看进程的名称
    x.pid #进程的pid
    
    

    注意:在Windows中process()必须放到if __name__=='__main__'下

    获取进程pid

    import os
    import time
    print(f'子进程:{os.getpid()}')
    print(f'主进程:{os.getppid()}')
    

    1566351108003

    验证进程之间的空间

    进程与进程之间是有物理隔离,不能共享内存的数据(lock,队列)

    from multiprocessing import Process
    import time
    import os
    name='song'
    def task():
        global name
        name='111'
        print(f'{name}')
    if __name__=='__main__':
        p.Process(target=task)
        p.start()
        time.sleep(2)
        print(f'主开始{name}')
    
    
    from multiprocessing import Process
    import time
    import os
    lst=[11,22,33]
    def task():
        global name
        name.append(44)
        print(f'{lst}')
    if __name__=='__main__':
        p.Process(target=task)
        p.start()
        time.sleep(2)
        print(f'主开始{lst}')
    #可变不可变都会隔离
    

    join

    #join就是主进程先让子进程执行结束,再执行主进程
    from multiprocessing import Process
    import time
    def func(name):
        print(f'{name} is running')
        time.sleep(1)
        print(f'{name} is out')
    if __name__ == '__main__':
    	p = Process(target=task,args=('song',))  # 创建一个进程对象
    	p.start()
    	p.join()
    	print('==主开始')
    #多个子进程使用join
    from multiprocessing import Process
    import time
    def func(name,s):
        print(f'{name}开始')
        time.sleep(s)
        print(f'{name}结束')
    def func1(name,s):
        print(f'{name}开始')
        time.sleep(s)
        print(f'{name}结束')
    def func2(name,s):
        print(f'{name}开始')
        time.sleep(s)
        print(f'{name}结束')
    if __name__ == '__main__':
        times=time.time()
        li=[]
        for i  in range(1,4):
            x = Process(target=func,args=('song',i))
            x.start()
            li.append(x)
    #
        for i in li:
            i.join()
        print('主进程开始')
        x=Process(target=func,args=('宋',3))
        x1=Process(target=func,args=('李',2))
        x2=Process(target=func,args=('王',1))
        x.start()
        x1.start()
        x2.start()
        #
        x.join()
        print(f'{time.time()-times}')
        x1.join()
        print(f'{time.time()-times}')
        x2.join()
        print(f'主进程开启{time.time()-times}')
    
    1. .代码优化

      from multiprocessing import Process
      import time
      def func(name,s):
          print(f'{name}开始')
          time.sleep(s)
          print(f'{name}结束')
      if __name__ == '__main__':
          times=time.time()
          li=[]
          for i  in range(1,4):
              x = Process(target=func,args=('song',i))
              x.start()
              li.append(x)
          for i in li:
              i.join()
              print('主进程开始')
      

    进程的其他参数

    x.terminate()   #杀死子进程
    x.join()        #先执行子进程,后执行主进程
    print(x.is_alive())   #判断进程还在不在 
    
    
    # from multiprocessing import Process
    # import time
    #
    # def task(name):
    #     print(f'{name} is running')
    #     time.sleep(2)
    #     print(f'{name} is gone')
    #
    #
    #
    # if __name__ == '__main__':
    #     # 在windows环境下, 开启进程必须在 __name__ == '__main__' 下面
    #     # p = Process(target=task,args=('常鑫',))  # 创建一个进程对象
    #     p = Process(target=task,args=('常鑫',),name='alex')  # 创建一个进程对象
    #     p.start()
    #     # time.sleep(1)
    #     # p.terminate()  # 杀死子进程  ***
    #     # p.join()  # ***
    #     # time.sleep(0.5)
    #     # print(p.is_alive())   # ***
    #     # print(p.name)
    #     p.name = 'sb'
    #     print(p.name)
    #     print('==主开始')
    

    守护进程

    #子进程守护主进程,只要结束主进程,子进程也随之结束
    x.daemon=True
    
    from multiprocessing import Process
    import time
    def func(name):
        print(f'{name}开始')
        time.sleep(1)
        print(f'{name}结束')
    if __name__ == '__main__':
        x.Process(target=func,args('song'))
        x.daemon=True   #在发送信号之前开启 守护进程,将X子进程设置成守护进程,只要主进程结束,守护进程马上结束
        x.start()
        x.join()
        print('666主进程开始')
    

    僵尸进程与孤儿进程(面试会问)

    1. 基于unix环境(Linux,macOS)
      • 主进程需要等待子进程结束之后,主进程才结束

    主进程时刻监测子进程的运行状态,当子进程结束之后,一段时间之内,将子进程进行回收/

    • 为什么主进程不在子进程结束会对其马上回收?

      • 主进程与子进程是异步关系,主进程无法马上捕获子进程什么时候结束
      • 如果子进程结束之后马上在内存中释放资源,主进程就没办法监测子进程的状态了
    • Unix针对于上面的问题,提供了一个机制

      所有的子进程结束之后,立马回释放掉文件的操作链接,内存的大部分数据,会保留一些内容,进程号,结束时间,运行状态,等待主进程监测,回收

    • 僵尸进程:所有的子进程结束之后,在准备回收之前,都会进入僵尸进程状态

    • 僵尸进程有危害:如果父进程不对僵尸进程进行回收(wait//waitpid),产生大量的僵尸进程,这样就会占用内存,占用进程pid号

    • 孤儿进程:父进程由于某种原因结束了,但是你的子进程还在运行中,这样你的这些子进程就成了孤儿进程,.你的父进程如果结束了.你的所有的孤儿进程就会被inIT进程回收,init就变成了你的父进程,对孤儿进程进行回收

    • 僵尸进程如何解决::::

      父进程产生了大量的子进程,但是不回收,这样就会形成大量的僵尸进程,解决方式就是直接杀死父进程将所有的僵尸进程变成孤儿进程然后init进行照顾,由init进程进行回收

    互斥锁

    三个同事,同时用一个打印机打印内容
    模拟三个进程模仿三个同事,输出平台模拟打印机
    from multiprocessing import Process
    import time,random
    def func1(name):
        print(f'{name}开始')
        time.sleep(random.randint(1, 3))
        print(f'{name}结束')
    def func2(name):
        print(f'{name}开始')
        time.sleep(random.randint(1, 3))
        print(f'{name}结束')
    def func3(name):
        print(f'{name}开始')
        time.sleep(random.randint(1, 3))
        print(f'{name}结束')
    if __name__ == '__main__':
        x1=Process(target=func1,args=('宋',))
        x2=Process(target=func2,args=('佳',))
        x3=Process(target=func3,args=('凡',))
        x1.start()
        x2.start()
        x3.start()
    #并发的抢占打印机
    #并发效率优先,但是不是顺序优先
    #多个进程共枪一个资源,需要保证顺序,一个一个来  串行
    
    
    版本二 加join 变成串行,但是这个顺序是固定的,
    
    
    版本三
    from multiprocessing import Process,Lock
    import time,random
    def func1(lock,name):
        lock.acquire()
        print(f'{name}开始')
        time.sleep(random.randint(1,3))
        print(f'{name}结束')
        lock.release()
    def func2(lock,name):
        lock.acquire()
        print(f'{name}开始')
        time.sleep(random.randint(1,3))
        print(f'{name}结束')
        lock.release()
    def func3(lock,name):
        lock.acquire()
        print(f'{name}开始')
        time.sleep(random.randint(1,3))
        print(f'{name}结束')
        lock.release()
    if __name__ == '__main__':
        lock=Lock()
        x1=Process(target=func1,args=(lock,'宋',))
        x2=Process(target=func2,args=(lock,'佳',))
        x3=Process(target=func3,args=(lock,'凡',))
        x1.start()
        x2.start()
        x3.start()
    #保证了顺序,保证了先到先得的原则,串行
    

    1566376485378

    join和lock的区别

    共同点:都可以阻塞,都可以把并发变成并发,保证了顺序
    不同点:join是人为的设定顺序,lock让其争抢顺序,保证了公平性
    

    进程之间的通信:

    进程在内存级别是隔离的,但是文件在磁盘上

    1. 基于文件通信

      1. 1566376925686
      抢票系统
      #思路分析:先可以查票,查询剩余票数  并发 都可以查
      #购买,向服务器发送请求,服务端接受,在后端将票数修改,返回给前端,串行 一个一个的买
      from multiprocessing import Process,Lock
      import os,time,random,json
      def search():
          time.sleep(random.randint(1,3))
          with open('song.json','r',encoding='utf-8')as f:
              dic=json.load(f)
              print(f'{os.getpid()}查看了票,还剩{dic["count"]}张票')
      def buy():
          with open('song.json','r',encoding='utf-8')as f1:
              dic=json.load(f1)
              if dic['count']>0:
                  dic['count']-=1
                  time.sleep(random.randint(1,3))
                  with open('song.json','w',encoding='utf-8')as f2:
                      json.dump(dic,f2)
                      print(f'{os.getpid()}购票成功')
      def run(lock):
          search()
          lock.acquire()
          buy()
          lock.release()
      if __name__ == '__main__':
          lock=Lock()
          for i in range(6):
              x= Process(target=run,args=(lock,))
              x.start()
      #当多个进程共枪一个数据时,保证数据安全,必须加锁和串行
      #互斥锁  可以公平的保证顺序的问题 以及数据的安全
      #基于文件的进程之间的通信
      	效率低
          自己加锁麻烦而且很容易出现死锁
      
    2. 基于队列通信

      1566377791348

      from multiprocessing import Queue
      q=Queue(3)    #里面可以限制最大有几个
      
      def func():
      	print(1)
      
      q.put(1)    #往队列里面放入1
      q.put('adfadf')
      q.put(func)     '啥也能放'
      
      q.get()
      q.get()
      print(q.get())      '一般放几个就取几个'
      print(q.get(timeout=3))  #阻塞三秒,给他计时,三秒之后还阻塞就主动抛出错误  
       
      队列:把队列理解成一个容器,这个容器可以承载一些数据
          特性:先进先出 永远保持这个数据,FIFO  羽毛球筒
      #如果队列里面是限制三个数据 要是放四个数据 或是取四个数据 会阻塞
      #解除阻塞 在别的进程里面取出来 或者添加
      print(q.get(block=False))   #只要遇到阻塞就会报错
      print(q.get(timeout=2))
      q.put(3,block=False) 
      q.put(3,timeout=2)    都报错
      
    3. 基于管道通信

    线程

    1. 生产者与消费者模型

      from multiprocessing import Process,Queue
      import time,random
      
      def producer(q,name):
          for i in range(1,6):
              ret=f'第{i}个包子'
              q.put(ret)
              print(f'生产者:{name},生产的{ret}')
      def consumer(q,name):
          while 1:
              try:
                  s1=q.get(timeout=2)
                  time.sleep(random.randint(1,3))
                  print(f'消费者:{name},吃了{s1}')
              except Exception:
                  return
      if __name__=='__main__':
          q=Queue()
          x=Process(target=producer,args=(q,'宋'))
          x1=Process(target=consumer,args=(q,'李'))
          x.start()
          x1.start()
      
      

      生产者消费者模型:编程思想,设计理念,理论等等,都是交给你一种编程的方法,以后遇到类似的情况,套用即可

      生产者消费者模型三要素:

      生产者:产生数据的

      消费者:接受数据做进一步处理

      容器:队列

      队列容易起到的作用:起到缓冲作用,平衡生产力和消费力 ,解耦

    线程的理论知识

    1.什么是线程
    	是一条流水线的工作流程
        进程:在内存中开启一个进程空间,然后将主进程的所有资源数据复制一份,然后调用CPU去执行这些代码
         开启一个进程:在内存中开启一个进程空间,然后将主进程的所有资源数据复制一份,然后调用线程去执行代码
            进程是资源单位,线程是执行单位
    

    1566483480160

    如何正确描述开启一个进程

    开启一个进程:进程会在内存,中开辟一个进程空间,将主进程的资源数据去复制一份,线程会执行里面的代码

    进程vs线程:

    1. 开启进程的开销非常大,比开启线程的开销大很多

    2. 开启线程的速度非常快,要比进程快几十上百倍

      from threading import Thread
      # from multiprocessing import Process
      # import os
      #
      # def work():
      #     print('hello')
      #
      # if __name__ == '__main__':
      #     #在主进程下开启线程
      #     t=Process(target=work)
      #     t.start()
      #     print('主线程/主进程')
      
      
      
      
      # 多线程
      # from threading import Thread
      # import time
      #
      # def task(name):
      #     print(f'{name} is running')
      #     time.sleep(1)
      #     print(f'{name} is gone')
      #
      #
      #
      # if __name__ == '__main__':
      #
      #     t1 = Thread(target=task,args=('海狗',))
      #     t1.start()
      #     print('===主线程')  # 线程是没有主次之分的.
      

    线程线程之间可以共享数据,进程与进程之间之间需要借助队列等办法实现通信

    # from threading import Thread
    # import os
    #
    # x = 3
    # def task():
    #     global x
    #     x = 100
    #
    # if __name__ == '__main__':
    #
    #     t1 = Thread(target=task)
    #     t1.start()
    #     t1.join()
    #     print(f'===主线程{x}')
    
    # 同一进程内的资源数据对于这个进程的多个线程来说是共享的.
    

    线程的应用:

    1. 并发:一个CPU看起来像是同时执行多个任务
    2. 单个进程开启三个线程,并发的执行任务
    3. 开启三个进程并发的执行任务
    4. 文本编辑器:
      1. 输入而文字
      2. 子啊屏幕上显示
      3. 保存在磁盘中
    5. 开启多线程就非常好了:数据共享,开销小,速度快
    6. 主线程子线程没有地位之分,但是一个进程谁在干活.:一个主线程在干活,当干完活了你需要等待其他线程干完活之后,才能结束本进程

    开启线程的两种方式

    #第一种
    from threading import Thread
    import time 
    def func():
        print('子线程开')
        time.sleep(1)
        print('子线程关')
    if __name__=='__main__':
        x=Thread(target=func)
        x.start()
        print('主线程开')
    #一般是子线程先开再开主线程
    
    #第二种
    from threading import Thread
    import time
    class A(Thread):
        def __init__(self,name):
            super().__init__()
            self.name=name
    	def run(self):        #必须要有run这个方法
            print('子线程开')
            time.sleep(1)
            print('子线程关')
    x=A('song')             #可以不写__name__=='__main__'
    x.start()
    print('主线程开')
    

    线程其他方法(了解

    from threading import Thread,enumerate,activeCount,CurrentThread
    import time,os,random
    def func():
        print(666)
    if __name__ == '__main__=':
        x=Thread(target=func)
        x.start()
        print(x.name)    #查询name属性  父类中是 Thread-1
        x.steName('song')    #添加name属性或者修改name属性
        print(x.getname())   #查获name属性
        print(x.isAlive)     #返回线程是否活动的
        print(currentThread())   #返回当前的线程变量
        print(enumernate())     #返回一个包换正在运功的线程列表list 线程启动后,结束前
        print(activecount())  #返回正在运行的线程数量
        
     #主线程等待子线程结束   
    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
        '''
    

    join与守护线程(考点)

    #join  阻塞 告知主线程要等待子线程执行完毕后再执行主线程
    
    from threading import Thread
    import time
    #
    def task(name):
        print(f'{name} is running')
        time.sleep(1)
        print(f'{name} is gone')
    #
    #
    
    if __name__ == '__main__':
        start_time = time.time()
        t1 = Thread(target=task,args=('海狗',))
        t2 = Thread(target=task,args=('海狗1',))
        t3 = Thread(target=task,args=('海狗2',))
    #
        t1.start()
        t1.join()
        t2.start()
        t2.join()
        t3.start()
        t3.join()
        print(f'===主线程{time.time() - start_time}')  # 线程是没有主次之分的.
        
    $$$$守护线程
    from multiprocessing import Process
    import os,time,random 
    def func():
        print('子进程开')
        time.sleep(1)
        print('子进程罐')
    def foo():
        print('1  kai')
        time.sleep(1)
        print('1  guan')
    if __name__=='__main__':
        x=Process(target=func)
        x1=Process(target=foo)
        x.daemon=True
        x.start()
        x1.start()
        time.sleep(1)      #注意没有睡眠一秒 就会直接不执行x子进程
        print('主进程开')
    $$$$守护线程
    from threading import Thread
    import time
    def func(name):
        print('zou')
        time.sleep(2)
        print('gunle')
    if __name__ == '__main__':
        x=Thread(target=func,args=('宋',))
        x1=Thread(target=func,args=('反',))
        x1.daemon=True
        x.start()
        x1.start()
        print('主线程开')
    #主线程什么时候结束:
    非守护进程与主线程结束之后,再结束
    

    互斥锁(线程 考点)

    from threading import Thread
    import time
    import random
    x = 10
    
    def task():
        time.sleep(random.randint(1,2))
        global x
        temp = x
        time.sleep(random.randint(1, 3))
        temp = temp - 1
        x = temp
    if __name__ == '__main__':
        l1 = []
        for i in range(10):
            t = Thread(target=task)
            l1.append(t)
            t.start()
    
        for i in l1:
            i.join()
        print(f'主线程{x}')
        #多个任务共抢一个数据,保证数据的安全的目的,要让其串行
        
    from threading import Thread
    from threading import Lock
    import time
    import random
    x = 100
    
    def task(lock):
    
        lock.acquire()
        # time.sleep(random.randint(1,2))
        global x
        temp = x
        time.sleep(0.01)
        temp = temp - 1
        x = temp
        lock.release()
    
    
    if __name__ == '__main__':
        mutex = Lock()
        l1 = []
        for i in range(100):
            t = Thread(target=task,args=(mutex,))
            l1.append(t)
            t.start()
    
        time.sleep(3)
        print(f'主线程{x}')
    

    死锁现象递归锁(RLock

    from threading import Thread,Lock
    import time
    locka=Lock()
    lockb=Lock()
    class A(Thread):
        def run(self):
            self.f1()
            self.f2()
        def f1(self):
            locka.acquire()
            print(f'{self.name}拿到a')
            lockb.acquire()
            print(f'{self.name}拿到b')
            locka.release()
            lockb.release()
        def f2(self):
            lockb.acquire()
            print(f'{self.name}拿到b')
            time.sleep(0.1)
            locka.acquire()
            print(f'{self.name}拿到a')
            lockb.release()
            locka.release()
    if __name__ == '__main__':
        for i in range(3):
            x = A()
            x.start()
    

    1566551175238

    解决死锁用递归锁就可以,递归锁有一个计数功能,上锁加1,解锁-1

    只要递归锁上面的数字不为零,其他线程就不能抢锁

    from threading import Thread,RLock
    import time
    locka=lockb=RLock()
    class A(Thread):
        def run(self):
            self.f1()
            self.f2()
        def f1(self):
            locka.acquire()
            print(f'{self.name}拿到a')
            lockb.acquire()
            print(f'{self.name}拿到b')
            locka.release()
            lockb.release()
        def f2(self):
            lockb.acquire()
            print(f'{self.name}拿到b')
            time.sleep(0.1)
            locka.acquire()
            print(f'{self.name}拿到a')
            lockb.release()
            locka.release()
    if __name__ == '__main__':
        for i in range(3):
            x = A()
            x.start()
    #   RLock  递归锁使用方法 locka=loakb=RLock()
    $$$递归锁可以解决死锁现象,业务需要多个锁时,要先考虑递归锁
    

    信号量(Semaphore)

    也是一种锁,控制并发数量

    from threading import Thread,Semaphore,currentThread
    import time ,random
    s=Semaphore(5)   #Semaphore  赋值一个变量 限制分次数,然后用这个带上锁
    def func():
        s.acquire()
        print(f'{currentThread().name}厕所ing')
        time.sleep(random.randint(1,3))
        s.release()
    if __name__ == '__main__':
        for i in range(10):
            x=Thread(target=func,)
            x.start()
    

    GIL全局解释器锁

    1566552371631

    理论上来说,单个进程的多线程可以利用多核,但是开发cpython解释器的程序员,给进入解释器的线程加了锁

    1566552452215

    为什么加锁,优缺点

    当时都是单核时代,而且CPU价格非常贵,

    如果不加全局解释器锁,开发cpython解释器的程序员就会在源码内部各种主动加锁,解锁,非常麻烦,各种死锁现象,为了省事,直接进入解释器时给线程加了一个锁

    优点:保证了cpython解释器的数据资源的安全

    缺点:单个进程的多线程不能利用多核

    jpython以及pypy没有GIL锁

    多核时代,将GIL锁去掉可以吗?

    因为cpython解释器的所有的业务逻辑都是围绕着单个线程实现的,去掉这个GIL锁,几乎不可能

    1566552695304

    单个进程的多线程可以并发,但是不能利用多核,不能并行

    多个进程可以并行,并发

    GIL与Lock锁的区别

    相同点:都是同种锁,互斥锁

    不同点:GIL全局解释器锁,保护解释器内部的资源数据的安全

    ​ GIL锁,上锁 释放 无需手动操作

    ​ 自己代码中定义的互斥锁保护进程中的资源数据的安全

    ​ 自己定义的互斥锁必须自己手动上锁,释放锁

    1566554494992

    io计算密集型

    io密集型

    1566553126583

    #io密集型:单个进程的多线程合适 并发执行
    

    计算密集型

    1566553143861

    计算密集型:适合多进程的并行
    

    验证io计算密集型

    from threading import Thread
    from multiprocessing import Process
    import time,random
    # 计算密集型:单个进程的多线程并发vs进程的并发执行
    def  func():
        count=0
        for i in range(100000000):
            count+=1
    if __name__ == '__main__':
        times=time.time()
        lst=[]
        for i in range(4):
            x=Process(target=func)
            lst.append(x)
            x.start()
        for i in lst:
            i.join()
        print(f'{time.time()-times}')        #17.108332633972168
    
    
    if __name__ == '__main__':
        times=time.time()
        lst=[]
        for i in range(4):
            x=Thread(target=func)
            lst.append(x)
            x.start()
        for i in lst:
            i.join()
        print(f'{time.time()-times}')      #30.25704336166382
     总结:计算密集型,还是用多进程的并发效率高(前提是数据比较大   
    
    #io密集型
    # io密集型  单个进程的多线程并发vs多个进程的并发并行
    from threading import Thread
    from multiprocessing import Process
    import time,random
    def func():
        count=0
        time.sleep(random.randint(1,3))
        count+=1
    if __name__ == '__main__':
        times=time.time()
        li=[]
        for i in range(4):
            x=Process(target=func)
            li.append(x)
            x.start()
        for i in li:
            i.join()
        print(f'{time.time()-times}')        #多进程3.244175910949707
    
    if __name__ == '__main__':
        times=time.time()
        li=[]
        for i in range(4):
            x=Thread(target=func)
            li.append(x)
            x.start()
        for i in li:
            i.join()
        print(f'{time.time()-times}')       #多线程2.002326250076294
    计算io密集型的还是用多线程的并发合适效率高
    

    多线程实现socket通信

    无论是多线程还是多进程,如果按照上面的写法,来一个
    客户端请求,我就开一个线程,来一个请求开一个线程,
    应该是这样: 你的计算机允许范围内,开启的线程进程数
    量越多越好

    #服务端
    import socket,time
    from threading import Thread
    def foo(conn,addr):
        while 1:
            try:
                s=conn.recv(1024).decode('utf-8')
                print(f'{addr[1]}{s}')
                time.sleep(1)
                s1=input('<<<<').strip().encode('utf-8')
                conn.send(s1)
            except Exception:
                break
        conn.close()
    def func():
        server = socket.socket()
        server.bind(('127.0.0.1', 8848))
        server.listen(5)
        while 1:
            conn, addr = server.accept()
            x=Thread(target=foo,args=(conn,addr))
            x.start()
    if __name__ == '__main__':
        func()
        
    #客户端
    import socket
    client=socket.socket()
    client.connect(('127.0.0.1',8890))
    while 1:
        s=input('<<<<').strip().encode('utf-8')
        client.send(s)
        s1=client.recv(1024).decode('utf-8')
        print(f'{s1}')
    client.close()
    
    

    进程池,线程池(ProcessPoolExecutor,ThreadPoolExecutor)

    线程池:一个容器,这个容器限制住你开启线程的数量,比如四个,第一次肯定只能并发的处理四个任务,只要有任务完成,线程马上就会接下一个任务.以时间换空间
    	#默认进程池,是你的计算机cpu核数 
    	#默认线程池 是你的计算机CPU核数 *5  乘5
        #查看cpu核数 import  os
    	#			print(os.cpu_count())
    
    from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
    import os,time,random
    print(os.cpu_count())   #查看计算机核数
    def func():
        print(f'{os.getpid()}接客')
        time.sleep(random.randint(1,2))
    if __name__ == '__main__':           #进程池(并行+并发
        p=ProcessPoolExecutor()   # 默认不写,进程池里面的进程数与cpu个数相等
        for i in range(5):
            p.submit(func,)
    
    if __name__ == '__main__':           #线程池(并发
        p=ThreadPoolExecutor(3)      # 默认不写, cpu个数*5 线程数
        p.submit(func)
        p.submit(func)
        p.submit(func)
        p.submit(func)
        p.submit(func)
        p.submit(func)
    
  • 相关阅读:
    树世界
    清空 NumericUpDown
    没有评论的日子
    GetData.cs

    Hashtable 在程序中控制重复项
    Convert.ToInt32() VS System.Int32.Parse()
    饮食九要素
    添加 or 修改 的一个处理方式
    一个关于 电话号码 的正则表达式
  • 原文地址:https://www.cnblogs.com/sjf981012-/p/11403776.html
Copyright © 2011-2022 走看看