Python的多线程适用于I/O密集型任务,因为python有GIL锁,该锁为了保证线程的安全,同一时刻只有一个线程被CPU执行。
调用函数实现多线程:
#coding:utf-8
# python主程序也属于一个线程
import threading #线程模块
import time
def Hi(num):
print("hello %d\n"%num)
time.sleep(3)
if __name__ == '__main__':
t1=threading.Thread(target=Hi,args=(10,))#创建了一个线程对象t1
t1.start() # 运行线程
t2 = threading.Thread(target=Hi, args=(9,)) # 创建了一个线程对象t1
t2.start() # 运行线程
print("ending..........") 主线程
#hello 10
#hello 9 同时输出 hello9 hello10,ending
#ending.......... 过3秒后程序结束
用类实现多线程
# coding:utf-8
import threading
import time
class MyThread(threading.Thread): # 定义类并继承threading.Thread类
def __init__(self, num):
threading.Thread.__init__(self) # 调用父类构造函数
self.num = num
def run(self): # 必须定义每个线程要运行的函数run
print("running on number:%s" % self.num)
time.sleep(3)
if __name__ == '__main__':
t1 = MyThread(1) # 生成线程对象t1
t2 = MyThread(2) # 生成线程对象t2
t1.start() # 运行
t2.start()
print("ending......")
#running on number:1 同时输出,3秒后程序结束
#running on number:2ending......
join方法让其他线程等待
#coding:utf-8
import threading
import time
def music():
print("begin to listen %s"%time.ctime())
time.sleep(3)
print("stop to listen %s" % time.ctime())
def game():
time.sleep(4)
t3=threading.Thread(target=music) # 创建线程t3
t3.start()
print("begin to play game %s"%time.ctime())
time.sleep(5)
print("stop to play game %s" % time.ctime())
if __name__ == '__main__':
t1= threading.Thread(target=music)
t2 = threading.Thread(target=game)
t1.start()
t2.start()
t1.join() # join函数让其他未join线程等待该进程结束
t2.join()
print("ending")
# 输出:
begin to listen Sat Mar 24 21:57:02 2018
stop to listen Sat Mar 24 21:57:05 2018
begin to listen Sat Mar 24 21:57:06 2018begin to play game Sat Mar 24 21:57:06 2018
stop to listen Sat Mar 24 21:57:09 2018
stop to play game Sat Mar 24 21:57:11 2018
ending
设置守护线程
一般的主线程,必须等所有子线程程结束后自己才能结束,但是当某个子线程被设置成守护线程时,主线程不必等该线程结束,该线程会守护主动随着主线程的结束而结束。
import threading
from time import ctime,sleep
import time
def ListenMusic(name):
print ("Begin listening to %s. %s" %(name,ctime()))
sleep(3)
print("end listening %s"%ctime())
def RecordBlog(title):
print ("Begin recording the %s! %s" %(title,ctime()))
sleep(5)
print('end recording %s'%ctime())
threads = []
t1 = threading.Thread(target=ListenMusic,args=('水手',)) #args线程执行函数传参
t2 = threading.Thread(target=RecordBlog,args=('python线程',))
threads.append(t1) #将t1,t2加入线程队列
threads.append(t2)
if __name__ == '__main__':
#t1.setDaemon(True)
t2.setDaemon(True)
for t in threads: # 从线程队列中读取数据
t.setDaemon(True) #注意:设置守护线程一定在start之前设置
t.start()
print(t.getName())
print("count:",threading.active_count()) # 统计运行线程数
#t.join()#此处加join的话,会变成串行
#t.join()
t1.join() # 让主线程等待
#t1.setDaemon(True)
#t2.join()########考虑这三种join位置下的结果
while threading.active_count()==1:
print ("all over %s" %ctime())
多线程导致数据不可重复读
由于多线程并发执行,可能导致数据读取与写入时出现顺序错误导致结果不可重复读,代码演示如下
import threading
import time
def sub():
global num
temp=num
time.sleep(0.0001)
num=temp-1
num=100
l=[]
for i in range(100):
t=threading.Thread(target=sub)
t.start()
l.append(t)
for t in l:
t.join()
print(num)
利用加锁机制处理线程同步
import threading
import time
def sub():
global num
lock.acquire() # 获得锁
temp=num # 操作数据
time.sleep(0.0001)
num=temp-1
lock.release() # 释放锁
num=100
l=[]
lock=threading.Lock() # 用threading.Lock()产用生一把锁
for i in range(100):
t=threading.Thread(target=sub)
t.start()
l.append(t)
for t in l:
t.join()
print(num)
利用信号量实现线程同步
import threading,time
class myThread(threading.Thread):
def run(self):
if semaphore.acquire():
print(self.name)
time.sleep(3)
semaphore.release()
if __name__=="__main__":
semaphore=threading.Semaphore()
thrs=[]
for i in range(100):
thrs.append(myThread())
for t in thrs:
t.start()
用于实现线程通信的队列用法
import queue # 线程 队列
q=queue.Queue(3) # FIFO模式
q.put(12)
q.put("hello")
q.put({"name":"yuan"})
# q.put_nowait(56)# q.put(block=False)
print(q.qsize())
print(q.empty())
print(q.full())
# q.put(34,False)
while 1:
data=q.get()
print(data)
print("----------")
用event事件同步线程对象
import threading,time
class Boss(threading.Thread):
def run(self):
print("BOSS:今晚大家都要加班到22:00。")
print(event.isSet())# False
event.set()
time.sleep(5)
print("BOSS:<22:00>可以下班了。")
print(event.isSet())
event.set()
class Worker(threading.Thread):
def run(self):
event.wait()# 一旦event被设定,等同于pass
print("Worker:哎……命苦啊!")
time.sleep(1)
event.clear()
event.wait()
print("Worker:OhYeah!")
if __name__=="__main__":
event=threading.Event()
threads=[]
for i in range(5):
threads.append(Worker())
threads.append(Boss())
for t in threads:
t.start()
for t in threads:
t.join()
print("ending.....")
# 输出:
BOSS:今晚大家都要加班到22:00。
False
Worker:哎……命苦啊!
Worker:哎……命苦啊!
Worker:哎……命苦啊!
Worker:哎……命苦啊!
Worker:哎……命苦啊!
BOSS:<22:00>可以下班了。
False
Worker:OhYeah!
Worker:OhYeah!
Worker:OhYeah!
Worker:OhYeah!
Worker:OhYeah!
ending.....
用递归锁防止线程死锁
import threading
import time
class MyThread(threading.Thread):
def actionA(self):
r_lcok.acquire() #count=1
print(self.name,"gotA",time.ctime())
time.sleep(2)
r_lcok.acquire() #count=2
print(self.name, "gotB", time.ctime())
time.sleep(1)
r_lcok.release() #count=1
r_lcok.release() #count=0
def actionB(self):
r_lcok.acquire()
print(self.name, "gotB", time.ctime())
time.sleep(2)
r_lcok.acquire()
print(self.name, "gotA", time.ctime())
time.sleep(1)
r_lcok.release()
r_lcok.release()
def run(self):
self.actionA()
self.actionB()
if __name__ == '__main__':
# A=threading.Lock()
# B=threading.Lock()
r_lcok=threading.RLock()
L=[]
for i in range(5):
t=MyThread()
t.start()
L.append(t)
for i in L:
i.join()
print("ending....")
生产者消费者模型
import time,random
import queue,threading
q = queue.Queue()
def Producer(name):
count = 0
while count <10:
print("making........")
time.sleep(5)
q.put(count)
print('Producer %s has produced %s baozi..' %(name, count))
count +=1
#q.task_done()
q.join()
print("ok......")
def Consumer(name):
count = 0
while count <10:
time.sleep(random.randrange(4))
# if not q.empty():
# print("waiting.....")
#q.join()
data = q.get()
print("eating....")
time.sleep(4)
q.task_done()
#print(data)
print('\033[32;1mConsumer %s has eat %s baozi...\033[0m' %(name, data))
# else:
# print("-----no baozi anymore----")
count +=1
p1 = threading.Thread(target=Producer, args=('A君',))
c1 = threading.Thread(target=Consumer, args=('B君',))
c2 = threading.Thread(target=Consumer, args=('C君',))
c3 = threading.Thread(target=Consumer, args=('D君',))
p1.start()
c1.start()
c2.start()
c3.start()