• 网络编程------同一进程内的队列(线程) 线程池相关问题


    统一进程内的队列(多线程)

      import queue

      queue.Queue()    # 先进先出

      queue.LifoQueue()  # 后进先出(先进后出)

      queue.PriorityQueue() 优先级队列

        优先级队列   q = queue.PriorityQueue()

                 q.put()  # 接收到的是一个元组类型的数据.

               元组中第一个额参数是: 表示当前数据的优先级.

               元组中第二个参数是:  需要存放到队列中的数据.

            优先级的比较(首先保证整个队列中, 所有表示优先级的数据类型必须一致)

               如果都是int,  比较数值大小(在ASCII码中只有0-9, 如果出现两位数字会先比较

               第一位数, 如果第一位数相同在比较第二位, 如果第一位就比较出优先级, 后面

               就不再继续比较.)

               如果是str, 比较字符串的大小(从第一个字符的ASCII码开始比较)

    from multiprocessing import Queue
    # 用于多进程对列, 就是专门用来做进程间通信的(IPC)
    import queue # 是用于统一进程内的队列, 不能做多进程之间的通信.
    
    # q = queue.Queue()
    # # 先进先出
    # q.put(1)
    # q.put(2)
    # q.put(3)
    
    # print(q.get())
    # print(q.get())
    # print(q.get())
    # # get()不需要传参数,
    
    # q1 = queue.LifoQueue()
    # # 线进后出
    
    # q1.put(1)
    # q1.put(2)
    # q1.put(3)
    
    #
    print(q1.get()) # print(q1.get()) # print(q1.get()) # # get()不需要传参数, q2 = queue.PriorityQueue() # 优先级输出 q2.put((1,'1')) q2.put((3,'3')) q2.put((2,'2')) # 传入的是一个元组 print(q2.get()) print(q2.get()) print(q2.get()) # get()不需要传参数 # 当表示优先级的第一个元素为一位数数字时, 会直接比较. 当是两位数字的时候 # 会先比较第一位数, 如果比较出大小,将停止比较进行输出, 否则继续比较下一位.

    多线程:

    threading模块可以创建多个线程,不过由于GIL锁的存在,Python在多线程里面其实是快速切换

    多线程与多进程的对比:

    from threading import Thread
    from multiprocessing import Process
    import time
    
    def func_daemon():
        time.sleep(3)
        # print('这是守护进程')
        print('这是守护线程')
    
    def func():
        time.sleep(1)
        # time.sleep(5)
        # print('这是普通进程')
        print('这是普通线程')
    # 守护进程是随着父进程的代码执行结束而结束
    # 守护线程不是随着父线程的代码执行结束而结束
    # 守护线程是随着父线程的执行结束而结束
    if __name__ == '__main__':
        t = Thread(target=func_daemon,)
        t.daemon = True
        t.start()
        t1 = Thread(target=func, )
        t1.start()
        print('这里是父线程')
        time.sleep(20)
        # p = Process(target=func_daemon, )
        # p.daemon = True
        # p.start()
        # p1 = Process(target=func, )
        # p1.start()
        # print('这是父进程')

    多线程的条件:

    from threading import Condition,Thread
    import time
    
    def func(con,i):
        con.acquire()# 主线程和10个子线程都在抢夺递归锁的一把钥匙。
        # 如果主线程抢到钥匙,主线程执行while 1,input,然后notify发信号,还钥匙。但是,此时如果主线程执行特别快
        # 极有可能接下来主线程又会拿到钥匙,那么此时哪怕其他10个子线程的wait接收到信号,但是因为没有拿到钥匙,所以其他子线程还是不会执行
        con.wait()
        print('第%s个线程执行了'%i)
        con.release()
    
    con = Condition()
    for i in range(10):
        t = Thread(target=func,args = (con,i))
        t.start()
    while 1:
        # print(123)
        con.acquire()
        num = input('>>>')
        con.notify(int(num))
        con.release()
        time.sleep(0.5)
    
    # 条件 涉及 4个方法:
    #    con.acquire()
    #    con.release()
    #    con.wait()  # 假设有一个初始状态为False,阻塞。一旦接受到notify的信号后,变为True,不再阻塞
    #    con.notify(int)  给wait发信号,发int个信号,会传递给int个wait,让int个线程正常执行

    多线程之条件:

    from threading import Condition,Thread
    # Thread    美 /θrɛd/
    # Condition  美 /kən'dɪʃən/
    import time
    
    def func(con,i):
        con.acquire()
    # 主线程和10个子线程都在抢夺递归锁的一把钥匙。 # 如果主线程抢到钥匙,主线程执行while 1,input,然后notify发信号,还钥匙。 # 但是,此时如果主线程执行特别快 # 极有可能接下来主线程又会拿到钥匙,那么此时哪怕其他10个子线程的wait接收到信号, # 但是因为没有拿到钥匙,所以其他子线程还是不会执行

    con.wait() print(i) con.release() con = Condition() for i in range(10): Thread(target=func,args=(con,i)).start() while 1: con.acquire() num = int(input(">>>")) con.notify(num) con.release() time.sleep(0.5) # 条件判断涉及4个方法: # con.acquire() # 拿钥匙锁门 # con.release() # 还钥匙开门 # con.notify() # 给wait 发int个信号, 会传递给int个wait, 让int个线程正常执行. # con.wait() # 假设有一个初始状态为False, 阻塞.一旦接收到notify的信号,变为Ture, 不再阻塞.

    线程池相关内容:

    概念:

      在一个池子中, 方固定数量的线程, 这些线程等待任务, 一旦有任务来, 就有线程自发的去执行任务

    #  concurrent.futures   这个模块是异步调用机制.     其提交任务都是用submit

    #  for + submit  多个任务的提交.

    #  shutdown  是等效于Pool 中的 close + join.  是指不逊于再继续相持中增加任务, 然后让父进程(线程)等待

    #  如何把多个任务扔进池中:

      要么使用 for + submit 的方式去提交多个任务.

      要么直接使用map(func, iterable) 方式去提交多个任务

    不同的方式提交多个任务(for + submit   或者 map), 拥有不同的那结果的方式,

      如果是for + submit 的方式提交任务, 那结果用result方法.

      如果是map的方式提交任务, 结果是一个生成器, 采用__next__的方式去拿结果.

     线程池中多任务提交:

    方法一

    from concurrent.futures import ThreadPoolExecutor
    # concurrent.futures 这个模块是异步调用的机制.
    # 其提交任务都是用submit
    # for + submit 多个任务提交
    import time
    
    def func(num):
        sum = 0
        for i in range(num):
            sum += i ** 2
        print(sum)
    
    t = ThreadPoolExecutor(20)
    start = time.time()
    t.map(func,range(1000))# 提交多个任务给池中。  等效于 for + submit
    t.shutdown()
    print(time.time() - start)

    多任务提交方法二

    from concurrent.futures import ThreadPoolExecutor
    # concurrent.futures 这个模块是异步调用的机制.
    # 其提交任务都是用submit
    # for + submit 多个任务提交
    import time
    
    def func(num):
        sum = 0
        for i in range(num):
            sum += i ** 2
        print(sum)
    
    t = ThreadPoolExecutor(20)
    start = time.time()
    for i in range(20):
    t.submit(func, i)
    t.shutdown()
    print(time.time() - start)

    进程池线程池效率比较:

    # 结果:针对计算密集的程序来说
    #   不管是Pool的进程池还是ProcessPoolExecutor()的进程池,执行效率相当
    #   ThreadPoolExecutor 的效率要差很多
    #   所以 当计算密集时,使用多进程。
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    from multiprocessing import Pool
    import time
    
    # def func(num):
    #     sum = 0
    #     for i in range(num):
    #         for j in range(i):
    #             for x in range(j):
    #                 sum += x ** 2
    #     print(sum)
    
    # if __name__ == '__main__':
        # pool D的进程池效率演示:
    
        # p = Pool(5) # 定义的进程池中的进程数为CPU核数+1
        # start = time.time()
        # for i in range(100):
        #     p.apply_async(func, args=(i,))
        # p.close()
        # p.join()
        # print(time.time() - start)
    
    
        # concurrent.futures中的多进程效率
        
        # p1 = ProcessPoolExecutor(5)
        # start1 = time.time()
        # for i in range(100):
        #     p1.submit(func, i)
        # p1.shutdown()
        # print(time.time() - start1)
        
        
        # 线程的效率:
        
        # p2 = ThreadPoolExecutor(20)
        # start2 = time.time()
        # for i in range(1000):
        #     p2.submit(func,i)
        # p2.shutdown()
        # print(time.time() - start2)
    
    # 结果:针对计算密集的程序来说
    #   不管是Pool的进程池还是ProcessPoolExecutor()的进程池,执行效率相当
    #   ThreadPoolExecutor 的效率要差很多
    #   所以 当计算密集时,使用多进程。

    进程池返回值:

    from concurrent.futures import ThreadPoolExecutor
    import time

    # def func(num):
    # sum = 0
    # for i in range(num):
    # sum += i**2
    # return sum
    #
    # if __name__ == '__main__':
    # q = ThreadPoolExecutor(20)
    # 下列代码是用for + submit提交多个任务的方式,对应拿结果的方法是result
    # l = []
    # for i in range(1000):
    # f = q.submit(func,i)
    # l.append(f)
    # q.shutdown()
    # [print(i.result()) for i in l]
    # 在Pool进程池中拿结果,是用get方法。 在ThreadPoolExecutor里边拿结果是用result方法

    # q1 = ThreadPoolExecutor(20)
    # 下列代码是用map的方式提交多个任务,
    # 对应 拿结果的方法是__next__() 返回的是一个生成器对象
    # f = q1.map(func,range(1000))
    # q1.shutdown()
    # print(f.__next__())
    # print(f.__next__())
    # print(f.__next__())

    回调函数:

    from concurrent.futures import ProcessPoolExecutor
    # 不管是ProcessPoolExecutor的进程池  还是Pool的进程池,回调函数都是父进程调用的。
    import os
    import requests
    
    
    
    def func(num):
        sum = 0
        for i in range(num):
            sum += i ** 2
        return sum
    
    def call_back_fun(res):
        # print(res.result(),os.getpid())
        print(os.getpid())
    
    if __name__ == '__main__':
        print(os.getpid())
        t = ProcessPoolExecutor(20)
        for i in range(1000):
            t.submit(func,i).add_done_callback(call_back_fun)
        t.shutdown()
  • 相关阅读:
    安装mysql apache php smb
    解决IE8placeholder属性问题
    将博客搬至CSDN
    shell脚本获取配置文件中的内容
    shell sed指令全解
    salt一键部署hive
    salt一键部署habse
    salt一键部署kafka
    salt一键部署elasticsearch
    salt一键部署mysql
  • 原文地址:https://www.cnblogs.com/hfbk/p/9544659.html
Copyright © 2020-2023  润新知