day33 GIL锁 线程队列 线程池

1.    全局解释器锁GIL

Python代码的执行由Python虚拟机(也叫解释器主循环)来控制。Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行。虽然 Python 解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。
  对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线程在运行。

  在多线程环境中,Python 虚拟机按以下方式执行:

  a、设置 GIL;

  b、切换到一个线程去运行;

  c、运行指定数量的字节码指令或者线程主动让出控制(可以调用 time.sleep(0));

  d、把线程设置为睡眠状态;

  e、解锁 GIL;

  d、再次重复以上所有步骤。
  在调用外部代码(如 C/C++扩展函数)的时候,GIL将会被锁定,直到这个函数结束为止(由于在这期间没有Python的字节码被运行,所以不会做线程切换)编写扩展的程序员可以主动解锁GIL。

 

 

2.   线程队列

queue队列 :使用import queue,用法与进程Queue一样

queue is especially useful in threaded programming when information must be exchanged safely between multiple threads.

class queue.Queue(maxsize=0) #先进先出
import queue
#先进先出型
q=queue.Queue(3)
q.put(3)
q.put(2)
q.put(1)

print(q.get())
print(q.get())
print(q.get())

"""
结果
3
2
1
"""
先进先出型

class queue.LifoQueue(maxsize=0) #last in fisrt out

import queue

q=queue.LifoQueue()
q.put(1)
q.put(2)
q.put(3)

print(q.get())
print(q.get())
print(q.get())
"""
结果
3
2
1

"""
先进后出行

 class queue.PriorityQueue(maxsize=0) #存储数据时可设置优先级的队列

import queue

q=queue.PriorityQueue()
#put进入一个元组,元组的第一个元素一般是优先级(一般是数字,也可以是非数字),数字越小,优先级越小
q.put((-1,"a"))
q.put((0,"b"))
q.put((10,"c"))
q.put((20,"d"))

print(q.get())
print(q.get())
print(q.get())
print(q.get())

"""
结果
数字越小,优先级越高,越优先输出
(-1, 'a')
(0, 'b')
(10, 'c')
(20, 'd')


"""
优先级队列

或者

 

import queue


class A:
    def __init__(self, property, value):
        self.property = property
        self.value = value

    def __lt__(self, other):
        return self.property < other.property


a = A(1, 'a')
b = A(2, 'b')
c = A(3, 'aaaaa')
d = A(1, 'bbbb')

q = queue.PriorityQueue()
q.put(a)
q.put(b)
q.put(c)
q.put(d)

print(q.get().value)
print(q.get().value)
print(q.get().value)
print(q.get().value)


#############
a
bbbb
b
aaaaa

 

 

 

注:优先级相同的会根据第二元素比较,第二个元素是根据编码的顺序比较,并且第二个元素的类型必须一致并且,是有序的才可以比较

如果两个值的优先级一样,那么按照后面的值的acsii码顺序来排序,如果字符串第一个数元素相同,比较第二个元素的acsii码顺序

TypeError: unorderable types: dict() < dict() 不能是字典

优先级相同的两个数据,他们后面的值必须是相同的数据类型才能比较,可以是元祖,也是通过元素的ascii码顺序来排序

 

 

3.    Python标准模块--concurrent.futures

#1 介绍
concurrent.futures模块提供了高度封装的异步调用接口
ThreadPoolExecutor:线程池,提供异步调用
ProcessPoolExecutor: 进程池,提供异步调用
Both implement the same interface, which is defined by the abstract Executor class.

#2 基本方法
#submit(fn, *args, **kwargs)
异步提交任务

#map(func, *iterables, timeout=None, chunksize=1) 
取代for循环submit的操作

#shutdown(wait=True) 
相当于进程池的pool.close()+pool.join()操作
wait=True,等待池内所有任务执行完毕回收完资源后才继续
wait=False,立即返回,并不会等待池内的任务执行完毕
但不管wait参数为何值,整个程序都会等到所有任务执行完毕
submit和map必须在shutdown之前

#result(timeout=None)
取得结果

#add_done_callback(fn)
回调函数
import time,random
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

def func(n):
    time.sleep(random.randint(1,3))
    return n*n


if __name__ == '__main__':
    p=ProcessPoolExecutor(max_workers=4)
    list=[]
    for i in range(10):
        ret=p.submit(func,i)
        list.append(ret)
        print(ret.result())
    p.shutdown()
    for ret in list:
        print(ret.result())
from concurrent.futures import ThreadPoolExecutor

def func(n):
    return n**2

if __name__ == '__main__':
    t_p=ThreadPoolExecutor(max_workers=4)
    list=[]
    for i in range(10):
        ret=t_p.submit(func,i)#异步提交任务
        list.append(ret)
        # print(ret.result())   #等待任务提交之后拿去结果,拿不到就柱塞,拿到了就继续

    t_p.shutdown()
    print("主进程结束")
    for ret in list:
        print(ret.result())
    
ThreadPoolExecutor
from concurrent.futures import ThreadPoolExecutor


def func(n):
    return n*n
if __name__ == '__main__':
    t_p=ThreadPoolExecutor(max_workers=4)

    # for i in range(10):
    #     t_p.submit(func,i)
    t_p.map(func,range(10))  #map取代了for+submit
map的用法
from concurrent.futures import ThreadPoolExecutor

def get(n):
    return n*n
def call(m):
    print(">>",m)
    print(m.result())

if __name__ == '__main__':
    t_p=ThreadPoolExecutor(max_workers=4)

    for i in range(3):
        t_p.submit(get,i).add_done_callback(call)
        
"""
结果
>> <Future at 0x294c1d0 state=finished returned int> #必须.result才能拿到结果
0
>> <Future at 0x294c1d0 state=finished returned int>
1
>> <Future at 0x294c1d0 state=finished returned int>
4
"""

 

posted @ 2018-12-03 15:42  阿布_alone  阅读(174)  评论(0编辑  收藏  举报
TOP