import _thread
num=0
def add():
global num
for i in range(1000000):
num+=1
print(num)
for i in range(5):
_thread.start_new_thread(add,())
while True:
pass
线程冲突产生原因
多个线程存在
多个线程操作同一资源
基于类实现多线程
import threading
import time
import win32api
class Mythread(threading.Thread):
def run(self):
win32api.MessageBox(0, "我是内容", "我是标题", 1)
for i in range(5):
t=Mythread() # 初始化
t.start() # 开启
join方法
import threading
import time
import win32api
class Mythread(threading.Thread):
def run(self):
win32api.MessageBox(0, "我是内容", "我是标题", 1)
myThreadList=[]
for i in range(5):
t=Mythread() # 初始化
t.start() # 开启
myThreadList.append(t)
for thd in myThreadList:
thd.join()
import threading
import time
import win32api
class Mythread(threading.Thread):
def run(self):
win32api.MessageBox(0, "我是内容", "我是标题", 1)
for i in range(5):
t=Mythread() # 初始化
t.start() # 开启
# 相当于锁,只不过这个是限制执行该代码的线程数量
sem = threading.Semaphore(2)
sem = threading.BoundedSemaphore(2) # 两个方法差不多
sem.acquire()
代码
sem.release()
import threading, time
# 限制线程数量为2个
sem = threading.Semaphore(2)
def gothread():
with sem: # 锁定某段代码所能容纳线程数量
for i in range(10):
print(threading.current_thread().name, i)
time.sleep(1)
for i in range(5):
threading.Thread(target=gothread).start()
线程数量
sem = threading.Semaphore(2)
sem = threading.BoundedSemaphore(2) # 两个方法差不多
没有足够的线程也会执行,执行完不会等待线程一起结束,谁执行完成谁先结束
凑固定数量线程执行
import threading, time
bar=threading.Barrier(3) # 等待3个线程一起才执行
def sever():
bar.wait()
print(threading.current_thread().name, "start")
time.sleep(5)
print(threading.current_thread().name, "end")
for i in range(5):
threading.Thread(target=sever).start()
import threading, time
def go1():
with cond:
for i in range(10):
time.sleep(1)
print(threading.current_thread().getName(), i)
cond.notify() # 通知
def go2():
with cond:
for i in range(10):
time.sleep(1)
print(threading.current_thread().getName(), i)
if i==5:
cond.wait() # 通知
cond = threading.Condition()
threading.Thread(target=go2).start()
threading.Thread(target=go1).start()
线程通信与事件 Condition=LOCK+Event
线程条件变量
cond.notify() # 通知,不会通知自己
cond.wait() # 等待通知
wait必须有同一个notify通知之后才会走
生产者消费者模式
生产者消费者模式代码
import threading
import time
import queue
import random
class createThread(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,1000000) # 随机数
self.myqueue.put("input 生产者"+str(self.index)+"硅胶娃娃"+str(num)+"号")
print("input 生产者"+str(self.index)+"硅胶娃娃"+str(num)+"号")
self.myqueue.task_done()
class buyThread(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) # 最大容量为10个
for i in range(3):
createThread(i,myqueue).start() # 生产者
for i in range(8):
buyThread(i,myqueue).start()
生产者消费者模式分析
生产的速度可以小于于消费的速度
生产了一个才能消费一个
不会出现线程安全问题
线程池
import time
import threadpool
def show(str):
print("hello", str)
time.sleep(2)
nameList = ["hsgj","hsfdh","hsdh","ffdg"]
start_time = time.time()
pool = threadpool.ThreadPool(10) # 最大容量10个
requests = threadpool.makeRequests(show,nameList) # 构建请求列表: 第一个函数,第二个参数列表
for req in requests:
pool.putRequest(req) # 将请求压入线程池中执行
end_time = time.time()
print(end_time-start_time)
定时任务(定时线程)
import os
import threading
import time
def go():
os.system("start notepad")
timeThread = threading.Timer(5, go) # 延时5秒后执行
timeThread.start()
i = 0
while True:
time.sleep(1)
print(i)
i += 1
定时任务
threading.Timer(5, go).start()
第一个参数定时秒数
第二个参数要执行的方法
with在锁中的作用
with作用
lock = threading.Lock() # 创建一个锁
with lock:
pass
with解释
with会自动打开关闭锁
前台与后台线程(守护线程)
上代码
import threading
import tkinter.messagebox
class MyThread(threading.Thread):
def run(self):
# tkinter.messagebox.showerror(title="错误",message="错误")
for i in range(100):
print(i)
t = MyThread()
t.setDaemon(True) # 设置线程为后台线程
t.start()
前台与后台线程(守护线程)介绍
threading.Thread默认是前台线程
主线程不会等待后台线程(守护线程)
setDaemon必须放在start之前
_thread是后台线程
每个线程独立存储
import threading
import time
data = threading.local() # 为每个线程独立存储空间
t1 = lambda x:x+1
t2 = lambda x:x+"1"
def printdata(func,x):
data.x = x
print(id(data.x)) # 不同的地址
for i in rang(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()