python线程基础学习
1. 线程通信‘
2. 线程通信强化
3. condition线程通信与事件
4. 线程调度
5. 生产者消费者模式
6. 线程池
7. 定时线程
8. with用法
9. 前台线程
10. TLS
++++++++++++++++++++++++++++++++++++++++++++++
1.线程通信:
用set来激发事件以达到通知效果
import threading
import time
def goevent():
e=threading.Event() #事件
def go():
e.wait() #等待,后续代码不执行,等待set再执行
e.clear() #清理
print("go")
threading.Thread(target=go).start() #开启一个线程
return e
t=goevent()
time.sleep(5) #5s后才激发事件打印go
t.set() #激发事件
2.线程通信强化(传参):
import threading
import time
def goevent():
e=threading.Event() #事件
def go():
for i in range(10):
e.wait() #等待
e.clear() #重置
print(i,"go")
threading.Thread(target=go).start() #开启一个线程
return e
t=goevent()
for i in range(10):
time.sleep(i) # i s后才激发事件打印go
t.set() #通知
3.condition线程条件变量:
使用条件变量方式控制通信,达到条件即通知
import threading
import time
def go1():
with cond:
for i in range(10):
time.sleep(1)
print(threading.current_thread().name,i)
if i ==5:
cond.wait()
def go2():
with cond: #使用条件变量
for i in range(10):
time.sleep(1)
print(threading.current_thread().name,i)
cond.notify() #通知
cond=threading.Condition() #线程条件变量
threading.Thread(target=go1).start()
threading.Thread(target=go2).start()
4.线程调度用condition条件控制实现:
import threading
import time
def go1():
with cond:
for i in range(1,10,2):
time.sleep(1)
print(threading.current_thread().name,i)
cond.notify() #通知
cond.wait() #等待
def go2():
with cond:
for i in range(0,10,2):
time.sleep(1)
print(threading.current_thread().name,i)
cond.wait()
cond.notify()
cond = threading.Condition() # 线程条件变量
threading.Thread(target=go2).start()
threading.Thread(target=go1).start()
5.生产者-消费者模式
生产者-消费者模式,即生产者负责生产(往队列增加数据,但是有一定限度,满了即不再生产),消费者负责消费(从队列取出数据,队列为空则等待生产),以下是简单模拟生产者消费者模式:
import threading
import queue
import time
import random
#生产
class creatorTread(threading.Thread):
def __init__(self,index,myqueue):
threading.Thread.__init__(self)
self.index=index #索引
self.myqueue=myqueue #队列
def run(self):
while True:
time.sleep(3) #3秒生产一个
num=random.randint(1,100000) #随机数
self.myqueue.put("input 生产者"+str(self.index)+"奶茶"+str(num))
print("input 生产者"+str(self.index)+"奶茶"+str(num))
self.myqueue.task_done() #代表完成任务,在这里不执行
#消费
class buyerTread(threading.Thread):
def __init__(self,index,myqueue):
threading.Thread.__init__(self)
self.index=index #索引
self.myqueue=myqueue #队列
def run(self):
while True:
time.sleep(1)
item=self.myqueue.get() #抓取数据
if item is None:
break
print("客户",self.index,"物品",item)
self.myqueue.task_done() # 代表完成任务,在这里不执行
myqueue=queue.Queue(10) #0表示无限,10代表最大容量为10
for i in range(3):
creatorTread(i,myqueue).start() #3个生产者
for i in range(8):
buyerTread(i,myqueue).start() #8个消费者
6.线程池(threadpool):
创建线程池来控制线程数量,线程压入线程池后开始执行
import time
import threadpool #线程池
def show(str):
print("hello",str)
time.sleep(2)
namelist=["xiaoming","177"]
start_time=time.time()
pool=threadpool.ThreadPool(10) #最大容量
requests=threadpool.makeRequests(show,namelist) #设置参数,并发十个线程干活,函数,参数列表
for req in requests: #遍历每一个请求,并开始执行
pool.putRequest(req) #压入线程池开始执行
end_time=time.time()
print(end_time-start_time)
'''
def show(str):
print("hello",str)
time.sleep(2)
namelist=["xiaoming","177","szu"]
start_time=time.time()
for name in namelist:
show(name)
end_time=time.time()
print(end_time-start_time)
'''
7.定时线程
延时线程的执行
import time
import os
import threading
'''
i=0
while True:
time.sleep(1)
print("第",i,"秒")
i+=1
'''
def go():
while True:
time.sleep(3)
os.system("notepad")
timethread=threading.Timer(5,go) #延时5s后执行go,执行一次
timethread.start()
i=0
while True:
time.sleep(1)
print(i)
i+=1
8.with:
使用锁(LOCK)的过程中,可以使用with,来自动释放锁,用法如下:
import threading
import time
num=0 #全局变量多个线程可以读写,可用于线程传递数据,但需要用到event
mutex=threading.Lock() #创建一个锁
class Mythread(threading.Thread):
def run(self):
global num
with mutex:
#if mutex.acquire(1): #锁住成功,没有锁住成功则一直等待,1代表参数,独占
for i in range(100000): #锁定期间其他人不能干活
num+=1
#mutex.release() #释放锁
print(num)
mythread=[]
for i in range(5):
t=Mythread()
t.start()
mythread.append(t)
for t in mythread:
t.join()
print("over!")
'''
with mutex: #with自动打开,自动释放
#if mutex.acquire(1): #锁住成功,没有锁住成功则一直等待,1代表参数,独占
for i in range(100000): #锁定期间其他人不能干活
num+=1
'''
9.前台与后台线程
主线程必须等待前台线程执行,而不必要等待后台线程,threading.Thread默认是前台进程,主线程必须等前台
import threading
import time
import win32api
class Mythread(threading.Thread): #继承threading.Thread
def run(self): #run重写
win32api.MessageBox(0,"你的账户很危险","来自支付宝的问候",2)
mythread=[] #list
for i in range(5):
t=Mythread() #初始化
#t.setDaemon(True) #后台线程,主线程不等待后台线程
t.start()
mythread.append(t) #加入线程集合
#threading.Thread默认是前台进程,主线程必须等前台
print("over")
10.TLS
线程之间独立存储空间,是动态绑定的
import threading
import time
data = threading.local() #每个线程独立存储空间
t1=lambda x:x+1
t2=lambda x:x+"1"
def printdata(func,x): #func代表函数,x代表参数
data.x=x #data是一个类,动态绑定,线程互相独立,=1 =“1”,data.x每个线程中是独立的
print(id(data.x))
for i in range(5):
data.x=func(data.x)
print(threading.current_thread().name,data.x)
threading.Thread(target=printdata,args=(t1,1)).start()
threading.Thread(target=printdata,args=(t2,"1")).start()
总结
线程才刚刚开始,还很不熟练,具体的应用也不掌握,线程很重要,还需要加强练习。