三十、全局解释器锁,线程池,条件,定时器,线程队列,信号量和事件(线程)

一、线程池

from concurrent.futures import ThreadPoolExecutor
import time


def func(n):
    time.sleep(2)
    print(n)
    return n * n


def call_back(m):
    print("结果是:%s" % m.result())  # 拿到结果


tpool = ThreadPoolExecutor(max_workers=5)  # 默认不要超过cpu个数+1
# tpool.map(func,range(10))  # 使用map拿不到返回值
# for i in range(10):
#     t = tpool.submit(func, i).add_done_callback(call_back)  # 回调函数

t_list = []
for i in range(10):
    t = tpool.submit(func, i)  # 一次五个,异步执行
    t_list.append(t)
# tpool.shutdown()  # 起到 close 和join 作用   阻塞,所有线程池执行完
print("主线程:")
for t in t_list: print("***", t.result())  # 拿到返回值"""

 

二、全局解释器锁:gil

  全局锁:同一时刻只能有一个线程访问CPU,在Cpython中 在同一时刻 多个线程只能有一个被执行。

  原因:多个线程被CPU调度处理数据中,在解释型语言中系统没法识别,多个线程是否会在同一时刻访问相同数据,会出现不同CPU在同一时               刻,分别调用同一进程下多个线程,访问同一数据,进行增删改查,造成数据混乱,全局锁的出现就是为加强对数据的安全!

  疑问:既然有了全局锁为何数据还需要加锁?

   在全局变量中,多进程或者多线程去访问同一数据,当其中一个进程或者线程拿到数据,释放了全局锁,突然遇到阻塞,其他进程或者线程这              时候拿到也拿到相同数据,同时去执行,也会造成数据混乱。

  什么时候选择多进程和多线程:

高CPU:计算类>>>>>>>高CPU利用率(多进程
高IO:input 爬取网页 ,qq聊天,处理日志文件,读文件,处理web请求,读写数据库等等>>>>>>(多线程)

三、线程(信号量和事件)

1.多线程信号量:

from threading import Semaphore, Thread
import time


def func(sem, a, b):
    time.sleep(1)
    sem.acquire()
    print(a + b)
    sem.release()


sem = Semaphore(4)
for i in range(10):
    t = Thread(target=func, args=(sem, i, i + 5))
    t.start()

2.事件

应用:连接数据库 ,检测数据库的可连接情况

起两个线程:
第一个线程:连接数据库
等待一个信号 告诉我们之间的网络是通的
第二个线程:检测与数据库之间的网络是否连通
time。sleep(0,2) 2 将事件设置为True
# 事件被创建的时候
# false 状态 wait()阻塞
# true 状态 wait()非阻塞
# clear 设置状态为 False
# set 设置状态为 True"""
mport time, random
from threading import Event, Thread


def connect(e):
    count = 0
    while count < 3:
        e.wait(1)  # 状态为False 的时候,我只等待1s就结束
        if e.is_set() == True:
            print("连接数据库成功!")
            break

        else:
            count += 1
            print("第%d次连接失败" % count)
    else:
        raise TimeoutError("数据库连接异常")


def check_web(e):
    time.sleep(random.randint(0, 3))
    e.set()


e = Event()
t1 = Thread(target=connect, args=(e,))
t2 = Thread(target=check_web, args=(e,))
t1.start()
t2.start()
数据库检测通讯应用

四、条件

  Condition条件:更复杂锁
提供 acquire release
一个条件被创建之初,默认有一个False状态
False状态 会影响wait 一直处于等待状态
notify(int数据类型)制造几把钥匙,就能过去几个线程"""
from threading import Condition, Thread


def func(con, i):
    con.acquire()
    con.wait()  # 一直在等待钥匙,然后放行,有一把放一个,有10个放十个
    print("在第%s个循环里" % i)
    con.release()


con = Condition()
for i in range(10):
    Thread(target=func, args=(con, i,)).start()
while True:
    num = int(input(">>>>>>>:"))
    con.acquire()
    con.notify(num)  # 造钥匙
    con.release()

五、定时器

from threading import Timer
import time


def func():
    print("时间同步")


while True:
    t = Timer(5, func).start()  # 非阻塞
    time.sleep(5)

# 每5秒执行一次

六、线程队列

import queue

q = queue.Queue()
q.put(1)
q.put(2)
# q.put_nowait()
q.get()

# q = queue.LifoQueue()  # 栈 先进后出
# q.put(1)
# q.put(2)
# q.put(3)
# print(q.get())
# print(q.get())
# print(q.get())

q = queue.PriorityQueue()  # 优先级队列,谁的数小谁先出去
q.put((20, "a"))
q.put((10, "b"))
q.put((30, "c"))
q.put((1, "d"))
print(q.get())

 

 

        

posted @ 2019-08-15 16:37  凯帅  阅读(186)  评论(0编辑  收藏  举报