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

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

  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()

 

posted @ 2018-08-27 20:49  向往灬  阅读(274)  评论(0)    收藏  举报