# ========== 线程
#threading模块 创建 线程
# import os
# import time
# from threading import Thread
# 多线程并发
# def func(a,b):
# global g
# g = 0
# print(g,os.getpid())
#
# g = 100
# t_lst = []
# for i in range(10):
# t = Thread(target=func,args=(i,5))
# t.start()
# t_lst.append(t)
# for t in t_lst : t.join()
# print(g)
# class MyTread(Thread):
# def __init__(self,arg):
# super().__init__()
# self.arg = arg
# def run(self):
# time.sleep(1)
# print(self.arg)
#
# t = MyTread(10)
# t.start()
# 进程 是 最小的 内存分配单位
# 线程 是 操作系统调度的最小单位
# 线程直接被CPU执行,进程内至少含有一个线程,也可以开启多个线程
# 开启一个线程所需要的时间要远远小于开启一个进程
# 多个线程内部有自己的数据栈,数据不共享
# 全局变量在多个线程之间是共享的
# GIL锁(即全局解释器锁)
# 在Cpython解释器下的python程序 在同一时刻 多个线程中只能有一个线程被CPU执行
# 高CPU : 计算类 --- 高CPU利用率
# 高IO : 爬取网页 200个网页
# qq聊天 send recv
# 处理日志文件 读文件
# 处理web请求
# 读数据库 写数据库
#线程与进程的效率对比
# import time
# from threading import Thread
# from multiprocessing import Process
# def func(n):
# n + 1
#
# if __name__ == '__main__':
# start = time.time()
# t_lst = []
# for i in range(100):
# t = Thread(target=func,args=(i,))
# t.start()
# t_lst.append(t)
# for t in t_lst:t.join()
# t1 = time.time() - start
#
# start = time.time()
# t_lst = []
# for i in range(100):
# t = Process(target=func, args=(i,))
#
# t.start()
# t_lst.append(t)
# for t in t_lst: t.join()
# t2 = time.time() - start
# print(t1,t2)
# Thread实例对象的方法
# isAlive(): 返回线程是否活动的。
# getName(): 返回线程名。
# setName(): 设置线程名。
# 线程模块的 方法
# threading.active_count() # 线程的数量
#threading.current_thread() # 主线程,线程号
#threading.enumerate() #所有的线程数 , 和线程号 存在一个列表内
#threading.get_ident() # 进程号
#threading.currentThread(): 返回当前的线程变量。
# 守护i线程
# 守护进程随着主进程代码的执行结束而结束
# 守护线程会在主线程结束之后等待其他子线程的结束才结束
# 主进程在执行完自己的代码之后不会立即结束 而是等待子进程结束之后 回收子进程的资源
#1 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),
# 然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,
#2 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,
# 进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。
# import time
# from threading import Thread
# def func1():
# while True:
# print('*'*10)
# time.sleep(1)
# def func2():
# print('in func2')
# time.sleep(5)
#
# t = Thread(target=func1,)
# t.daemon = True
# t.start()
# t2 = Thread(target=func2,)
# t2.start()
# t2.join()
# print('主线程')
# 主进程在执行完自己的代码之后不会立即结束 而是等待子进程结束之后 回收子进程的资源
# import time
# from multiprocessing import Process
# def func():
# time.sleep(5)
#
# if __name__ == '__main__':
# Process(target=func).start()
# ============ 学到两种锁 互斥锁 和 递归锁
#死锁与递归锁
# 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,
# 若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,
# 这些永远在互相等待的进程称为死锁进程,如下就是死锁
# import time
# from threading import Lock,Thread
# Lock 互斥锁
# def func(lock):
# global n
# lock.acquire()
# temp = n
# time.sleep(0.2)
# n = temp - 1
# lock.release()
# n = 10
# t_lst = []
# lock = Lock()
# for i in range(10):
# t = Thread(target=func,args=(lock,))
# t.start()
# t_lst.append(t)
# for t in t_lst: t.join()
# print(n)
# 科学家吃面
# noodle_lock = Lock()
# fork_lock = Lock()
# def eat1(name):
# noodle_lock.acquire()
# print('%s拿到面条啦'%name)
# fork_lock.acquire()
# print('%s拿到叉子了'%name)
# print('%s吃面'%name)
# fork_lock.release()
# noodle_lock.release()
#
# def eat2(name):
# fork_lock.acquire()
# print('%s拿到叉子了'%name)
# time.sleep(1)
# noodle_lock.acquire()
# print('%s拿到面条啦'%name)
# print('%s吃面'%name)
# noodle_lock.release()
# fork_lock.release()
#
# Thread(target=eat1,args=('alex',)).start()
# Thread(target=eat2,args=('Egon',)).start()
# Thread(target=eat1,args=('bossjin',)).start()
# Thread(target=eat2,args=('nezha',)).start()
# from threading import RLock # 递归锁
# fork_lock = noodle_lock = RLock() # 一个钥匙串上的两把钥匙
# def eat1(name):
# noodle_lock.acquire() # 一把钥匙
# print('%s拿到面条啦'%name)
# fork_lock.acquire()
# print('%s拿到叉子了'%name)
# print('%s吃面'%name)
# fork_lock.release()
# noodle_lock.release()
#
# def eat2(name):
# fork_lock.acquire()
# print('%s拿到叉子了'%name)
# time.sleep(1)
# noodle_lock.acquire()
# print('%s拿到面条啦'%name)
# print('%s吃面'%name)
# noodle_lock.release()
# fork_lock.release()
#
# Thread(target=eat1,args=('alex',)).start()
# Thread(target=eat2,args=('Egon',)).start()
# Thread(target=eat1,args=('bossjin',)).start()
# Thread(target=eat2,args=('nezha',)).start()
# 信号量
# 信号量
# 同进程的一样
# Semaphore管理一个内置的计数器,
# 每当调用acquire()时内置计数器-1;
# 调用release() 时内置计数器+1;
# 计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。
# import time
# from threading import Semaphore,Thread
# def func(sem,a,b):
# sem.acquire()
# time.sleep(1)
# print(a+b)
# sem.release()
#
# sem = Semaphore(4)
# for i in range(10):
# t = Thread(target=func,args=(sem,i,i+5))
# t.start()
# 事件被创建的时候
# False状态
# wait() 阻塞
# True状态
# wait() 非阻塞
# clear 设置状态为False
# set 设置状态为True
#event.isSet():返回event的状态值;
# 线程 的 事件
# 数据库 - 文件夹
# 文件夹里有好多excel表格
# 1.能够更方便的对数据进行增删改查
# 2.安全访问的机制
# 起两个线程
# 第一个线程 : 连接数据库
# 等待一个信号 告诉我我们之间的网络是通的
# 连接数据库
# 第二个线程 : 检测与数据库之间的网络是否连通
# time.sleep(0,2) 2
# 将事件的状态设置为True
import time
import random
from threading import Thread,Event
# def connect_db(e):
# count = 0
# while count < 3:
# e.wait(0.5) # 状态为False的时候,我只等待1s就结束
# if e.is_set() == True:
# print('连接数据库')
# break
# else:
# count += 1
# print('第%s次连接失败'%count)
# else:
# raise TimeoutError('数据库连接超时')
#
# def check_web(e):
# time.sleep(random.randint(0,3))
# e.set()
#
# e = Event()
# t1 = Thread(target=connect_db,args=(e,))
# t2 = Thread(target=check_web,args=(e,))
# t1.start()
# t2.start()
# 条件
# 条件
# from threading import Condition
# 条件
# 锁
# acquire release
# 一个条件被创建之初 默认有一个False状态
# False状态 会影响wait一直处于等待状态
# notify(int数据类型) 造钥匙
# from threading import Thread,Condition
# def func(con,i):
# con.acquire()
# con.wait() # 等钥匙
# 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()
# 定时器
# 定时器
# 定时器,指定n秒后执行某个操作
# import time
# from threading import Timer
# def func():
# print('时间同步') #1-3
#
# while True:
# t = Timer(5,func).start() # 非阻塞的
# time.sleep(5)
# 线程的 队列
# queue
import queue
# q = queue.Queue() # 队列 先进先出
# q.put()
# q.get()
# q.put_nowait()
# q.get_nowait()
# q = queue.LifoQueue() # 栈 先进后出
# q.put(1)
# q.put(2)
# q.put(3)
# print(q.get())
# print(q.get())
# q = queue.PriorityQueue() # 优先级队列
# q.put((20,'a'))
# q.put((10,'b'))
# q.put((30,'c'))
# q.put((-5,'d'))
# q.put((1,'?'))
# print(q.get())
# 线程池
# concurrent.futures模块提供了高度封装的异步调用接口
# ThreadPoolExecutor:线程池,提供异步调用
# ProcessPoolExecutor: 进程池,提供异步调用
# Both implement the same interface, which is defined by the abstract Executor class.
#基本方法
#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
from concurrent.futures import ThreadPoolExecutor
# 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个数*5
# for i in range(20):
# tpool.submit(func,i).add_done_callback(call_back)
# tpool.map(func,range(20)) # 拿不到返回值
# t_lst = []
# for i in range(20):
# t = tpool.submit(func,i)
# t_lst.append(t)
# tpool.shutdown() # close+join #
# print('主线程')
# for t in t_lst:print('***',t.result())