"""
创建线程
(以及~~~线程间的数据共享)
"""
from threading import Thread # 创建线程必备
from threading import current_thread, active_count
import os
import time
def task1():
print("当前'线程'的名字>>>", current_thread().name)
print(f"{current_thread().name}的进程号>>>", os.getpid())
global age
age = age + 1
print(f"{current_thread().name}的age>>>", age)
def task2():
print("当前'线程'的名字>>>", current_thread().name)
print(f"{current_thread().name}的进程号>>>", os.getpid())
age = 666 # 本来age=19,但它在自己的空间建立了个age=666
print(f"{current_thread().name}的age>>>", age)
if __name__ == '__main__':
# 主线程的 age
age = 18
# 创建线程对象
t1 = Thread(target=task1)
t2 = Thread(target=task2)
# 开始线程
t1.start()
t2.start()
# 等待两个线程执行完毕,才继续主线程
t1.join()
t2.join()
# 子线程结束前,主线程不会结束,主线程结束意味着关闭"进程"及其里面的资源
print("当前'线程'的名字>>>", current_thread().name)
print(f"{current_thread().name}的进程号>>>", os.getpid())
# 输入主线程的 age
print(f"{current_thread().name}的age>>>", age)
守护线程
"""
守护线程
"""
from threading import Thread
import time
"""
主线程运行完毕后,它不会立刻结束,要等待所有子线程运行完毕才会结束
因为主线程的结束,意味着主线程所在的"进程"结束了
"""
def task(name):
print(f"{name}还活着")
time.sleep(3)
print(f"{name}正常死亡")
if __name__ == '__main__':
# 创建线程对象
t = Thread(target=task, args=("苏妲己",))
# 将线程的"守护线程"功能开启
t.daemon = True
# 开启线程
t.start()
# 主线程
print("纣王驾崩了")
线程互斥锁
"""
线程互斥锁
"""
import time
from threading import Thread, Lock
def task(mutex):
global num
# 加锁处理
mutex.acquire() # 枪锁
temp = num
time.sleep(0.05)
num = temp - 1
mutex.release() # 释放锁
if __name__ == '__main__':
# 主线程 num
num = 30
# 创建一个锁
mutex = Lock()
# 创建线程
l = [] # 获取30个线程对象
for i in range(30):
t = Thread(target=task, args=(mutex,))
t.start()
l.append(t)
# 等待所有子线程执行完毕,才执行主线程
for i in l:
i.join()
print("主线程的num>>>", num)
"""
信号量
———————————————————————————————————————————
信号量(Semaphore)是一种用于多线程编程的同步手段,
它可以控制同时访问某个共享资源的线程数量。
———————————————————————————————————————————
如果此时有其他线程请求获取信号量,它们就必须等待,直到有足够的资源被释放。
"""
from threading import Thread, Semaphore
import time
import random
def task(name, sp):
# 对"资源"进行访问限制(被限制的内容,最多被5个线程同时访问)
sp.acquire() # 资源限制开始
print(f"{name}抢到了停车位")
time.sleep(random.randint(3, 6))
sp.release() # 资源限制结束
if __name__ == '__main__':
# 创建信号量对象
sp = Semaphore(5) # 同时访问某个资源时,最多5个线程
# 创建20个线程
for i in range(20):
t = Thread(target=task, args=(f"路人{i + 1}号", sp))
t.start()
事件
"""
Event事件
"""
from threading import Thread, Event
import time
def bus():
print("公交车即将到站")
time.sleep(3)
print("公交车到站了")
event.set()
def passenger(name):
print(f"{name}正在等车")
event.wait()
print(f"{name}上车出发")
if __name__ == '__main__':
# 创建Event的对象
event = Event()
# 创建bus线程对象
t = Thread(target=bus)
t.start() # 开始线程
# 创建passenger线程对象
for i in range(10):
t = Thread(target=passenger, args=(f"乘客{i + 1}号",))
t.start() # 开始线程
线程池
"""
线程池(thread pool)
"""
from concurrent.futures import ThreadPoolExecutor
import time
def task(name):
print(f"路人{name}号")
time.sleep(1)
return name + 10
if __name__ == '__main__':
# 创建线程池
pool = ThreadPoolExecutor(5) # 线程池中的"线程数"10个,永远是这十个线程,只是内容和对象变了
# 往线程池中提交任务---"创建线程"(并非真正独立再建立一个新的线程)
f_list = []
for i in range(1, 31):
future = pool.submit(task, i) # 往线程池中提交任务,返回一个对象
f_list.append(future) # 把对象(地址)存起来
pool.shutdown() # 关闭线程池,等待线程池中所有任务运行完毕
for i in f_list: # 遍历对象
# 获得对象的result方法的值,若此result方法没有结果,则阻塞此处,等待它所对应的线程的运行结果
print("任务结果:", i.result())
进程池
"""
进程池(process pool)
"""
from concurrent.futures import ProcessPoolExecutor
import os
import time
def task(name):
print(f"对象{name}号-----{os.getpid()}")
time.sleep(3)
return name + 10
if __name__ == '__main__':
# 创建进程池
pool = ProcessPoolExecutor(3) # 一但进程池中进程的数量定下来后,永远都是这些进程在运作
# 运行30个进程,3个为一批,一批运行完后,再运行下一批,共运行10批。进程都是同样的那3个
f_list = []
for i in range(30):
future = pool.submit(task, i) # 往进程池中提交任务,返回一个对象,
f_list.append(future) # 把对象(地址)存起来
for i in f_list: # 遍历对象
# 获得对象的result方法的值,若此result方法没有结果,则阻塞此处,等待它所对应的进程的运行结果
print("任务结果:", i.result())
回调机制
"""
回调机制
"""
from concurrent.futures import ProcessPoolExecutor
import time
import os
def task(name):
print(f"进程{name}号 ---> 进程号>>>{os.getpid()}")
time.sleep(3)
return name + 10
def call_back(obj):
print("返回的结果>>>", obj.result())
if __name__ == '__main__':
# 创建进程池
pool = ProcessPoolExecutor(3)
# 发送任务
for i in range(1, 31):
# 异步回调机制
future = pool.submit(task, i).add_done_callback(call_back)
yield 进阶
# # 当函数有yield的时候,它已经是生成器函数了
# def f1():
# yield "hello"
# yield "world"
#
#
# g = f1() # 调用生成器函数不会执行函数体内容,它会得到一个可迭代的生成器对象
# print(next(g))
# print(next(g))
#
# for i in f1():
# print(i)
#
#
# def f2():
# return [i for i in range(100)]
#
#
# def f3():
# for i in range(100):
# yield i
#
#
# res = f3()
#
#
# def f4():
# res = yield "hello"
# yield res
#
#
# g = f4()
# print(next(g))
# print(g.send("world"))
# # yield from语句
# def f5():
# for s in "abc":
# yield s
# for i in range(3):
# yield i
#
#
# for i in f5():
# print(i)
#
#
# def f6():
# yield from "abc"
# yield from range(3)
#
#
# for i in f6():
# print(i)
def sub():
yield "a"
yield "b"
return "c"
def link():
res = yield from sub()
print("结果>>>", res)
g = link()
next(g)
next(g)
next(g)
协程
"""
协程:
也可以称为微线程,它是一种用户态内的上下文切换技术,简单说就是在单线程下实现并发效果
"""
import time
"""
进程:资源单位
线程:执行单位
协程:程序员人为创造出来的,不存在(切换+保存)
当程序遇到IO的时候,通过我们写的代码,让我们的代码自动完成切换
也就是我们通过代码来监听IO,一旦程序遇到IO,就在代码层面上自动切换,
给cpu的感觉是"咋回事,你这个程序没有IO操作?咋不让我歇会啊!!!""""
# # 单线程下执行技术密集型
# # 串行计数:0.44606804847717285
# # 切换计数:0.7273049354553223
# def f1():
# n =0
# for i inrange(10000000):
# n +=1
# yield
#
#
# def f2():
# g =f1()
# n =0
# for i inrange(10000000):
# n +=1
# next(g)
#
#
# start = time.time()
# f2()
# end = time.time()
# print(end - start)
# 单线程下执行IO密集型
from gevent import monkey
monkey.patch_all()
from gevent import spawn # spawn 有一定的问题,需要加上猴子补丁
def da():for _ inrange(3):print("哒")
time.sleep(0.5)
def mie():for _ inrange(3):print("咩")
time.sleep(2)
def buyao():for _ inrange(3):print("不要")
time.sleep(5)
start = time.time()
g1 =spawn(da) # 异步提交任务---执行并监听da()函数,有IO操作就跳到其他代码运行
g2 =spawn(mie)
g3 =spawn(buyao)
g1.join()
g2.join()
g3.join()
end = time.time()print(end - start) # 12.0030574798583986.050061464309692