Python多线程
Python多线程的使用及其相关概念介绍
异步与多线程的区别:https://www.cnblogs.com/dream844/archive/2012/06/12/2546083.html
1. 线程的基本使用
1.1 直接通过threading模块注册使用
# -*- coding:utf-8 -*- # Author:Wong Du ''' 多线程的简单使用 ''' import threading import time def war(n): for i in range(10): print("task ", n, i) time.sleep(2) # 注册线程 t1 = threading.Thread(target=war, args=("t1",)) t2 = threading.Thread(target=war, args=("t2",)) # 运行线程 t1.start() t2.start() # war("t1") # war("t2")
1.2 通过继承threading.Thead类,重写run函数方法来调用线程
# -*- coding:utf-8 -*- # Author:Wong Du import threading import time class MyThreading(threading.Thread): def __init__(self, n, sleep_time): super(MyThreading, self).__init__() self.n = n self.sleep_time = sleep_time def run(self): print("Task ", self.n) time.sleep(self.sleep_time) # 注册线程 t1 = MyThreading("t1", 2) t2 = MyThreading("t2", 4) # 运行线程 t1.start() t2.start() # 等待t1线程执行完才执行后续代码 t1.join() print("Task t1 is done...")
1.3 多线程并行执行
1 # -*- coding:utf-8 -*- 2 # Author:Wong Du 3 4 import threading 5 import time 6 7 # 定义一个函数任务,作为注册线程使用 8 def war(n): 9 print("task", n) 10 time.sleep(2) 11 12 # 注册的线程列表 13 t_list = [] 14 # 程序开始启动线程时间 15 start_time = time.time() 16 # 运行多个线程 17 for i in range(50): 18 t = threading.Thread(target=war, args=("t-%s" % i,)) 19 t.start() 20 # 把注册的线程加到列表里 21 t_list.append(t) 22 23 # join一下,等待所有线程执行完毕 24 for t in t_list: 25 t.join() 26 27 # 计算同时开启50个线程执行完毕花费的时间 28 print("\033[32;1mSpeed time is %s\033[0m" % (time.time() - start_time))
2. 子线程和守护线程
子线程:Python多线程的子线程和主线程相对独立,内存共享
守护线程:通过setDaemon(True)可将线程设置成守护线程,守护线程为非守护线程服务,当非守护线程都执行完毕时,无论守护线程是否执行完毕,都将被强制结束
# -*- coding:utf-8 -*- # Author:Wong Du ''' 子线程:Python多线程的子线程和主线程相对独立,内存共享 守护线程:通过setDaemon(True)可将线程设置成守护线程,守护线程为非守护线程服务 当非守护线程都执行完毕时,无论守护线程是否执行完毕,都将被强制结束 ''' import threading import time def war(n): print("task", n) # 由主线程申请调用出来的子线程 print("I am not main threading...".center(50, '-'), threading.currentThread()) time.sleep(2) print("%s 子线程执行完毕..." % threading.currentThread()) start_time = time.time() for i in range(50): t = threading.Thread(target=war, args=("t-%s" % i,)) # 将t线程设置为守护进程 t.setDaemon(True) t.start() # 查看当前线程信息 print("%s is started..." % threading.currentThread()) # 查看当前线程信息及当前程序活跃的线程 print("I am main threading...".center(50, '-'), threading.currentThread(), threading.active_count()) print("\033[32;1mSpeed time is %s\033[0m" % (time.time() - start_time))
3. Python线程锁和递归锁
# -*- coding:utf-8 -*- # Author:Wong Du import threading import time """ python 2.x中,会出现运算数据不正常的现象,可以通过自己加lock解决 python 3.x中,python内部进行了优化,无需加lock也不会出现异常 """ def war(): # 加锁 lock.acquire() global num num += 1 # time.sleep(0.1) # 释放锁 lock.release() time.sleep(0.1) num = 0 # 定义一把锁,当用锁锁住时,CPU不会进行上下文的切换,直到当前锁内的代码执行完毕 lock = threading.Lock() start_time = time.time() t_list = [] for i in range(50): t = threading.Thread(target=war) t.start() t_list.append(t) for j in t_list: j.join() print("Num:", num) print("\033[31;1mSpeed time: %s\033[0m" % (time.time() - start_time))
# -*- coding:utf-8 -*- # Author:Wong Du import threading import time """ python 2.x中,会出现运算数据不正常的现象,可以通过自己加lock解决 python 3.x中,python内部进行了优化,无需加lock也不会出现异常 Python中,为了避免“锁内加锁”而出现锁同名导致的程序无法正常退出问题, 引入了Rlock(递归锁)的方法来区分多个用户锁 """ def run1(): print("num") lock.acquire() global num num += 10 lock.release() return num def run2(): print("num2") lock.acquire() global num2 num2 += 1 lock.release() return num2 def run3(): lock.acquire() res1 = run1() print("Between run1 to run2...") res2 = run2() lock.release() print(res1, res2) time.sleep(3) num, num2 = 0, 0 # 定义递归锁,当用锁锁住时,CPU不会进行上下文的切换,直到当前锁内的代码执行完毕 lock = threading.RLock() for i in range(5): t = threading.Thread(target=run3) t.start() # print("Num:", num) while threading.active_count() != 1: pass # print(num, num2) else: print("Threading is done...") print(num, num2)
4. 多线程信号量控制
Python线程处理中,Semaphore信号量可以控制“同一时间”切换上下文执行线程的数量
# -*- coding:utf-8 -*- # Author:Wong Du import threading import time """ python 2.x中,会出现运算数据不正常的现象,可以通过自己加lock解决 python 3.x中,python内部进行了优化,无需加lock也不会出现异常 Python中,为了避免“锁内加锁”而出现锁同名导致的程序无法正常退出问题, 引入了Rlock(递归锁)的方法来区分多个用户锁 Python线程处理中,Semaphore信号量可以控制“同一时间”切换上下文执行线程的数量 """ def war(n): semaphore.acquire() time.sleep(1) print("Threading:", n) semaphore.release() # 定义信号量数,信号量锁住时,相当于"同一时间",只有5个线程进行上下文切换,即“同时”执行 semaphore = threading.BoundedSemaphore(5) for i in range(30): t = threading.Thread(target=war, args=(i, )) t.start()
5. 线程的事件管理
1 # -*- coding:utf-8 -*- 2 # Author:Wong Du 3 4 ''' 5 threading事件管理,下面为红绿灯编程实例 6 ''' 7 import threading 8 import time 9 10 # 创建一个线程事件 11 event = threading.Event() 12 13 def light(): 14 count = 0 15 # 将事件置为set状态 16 event.set() 17 while True: 18 if count > 5 and count < 10: 19 # 清除事件的set状态 20 event.clear() 21 print("\033[41;1mNow is red light...\033[0m") 22 elif count > 10: 23 # 将事件置为set状态 24 event.set() 25 # 重置计数 26 count = 0 27 else: 28 print("\033[46;1mNow is green light...\033[0m") 29 count += 1 30 time.sleep(1) 31 32 def car(name): 33 while True: 34 # 判断事件当前是否为set状态 35 if event.is_set(): 36 print("[%s] is running..." % name) 37 time.sleep(1) 38 else: 39 print("[%s] sees red light, waiting..." % name) 40 # 将事件置为wait状态,该线程卡住,只有当事件状态变为set时,才继续执行后面的代码 41 event.wait() 42 print("[%s] sees green light, running..." % name) 43 44 light0 = threading.Thread(target=light) 45 light0.start() 46 47 car1 = threading.Thread(target=car, args=("car1", )) 48 car1.start()
静静的学习一阵子儿...