''' 在Python中,可以通过继承threading.Thread类来创建线程。通过继承threading模块中Thread类来 创建新类,在新类中重写run方法,然后就可以通过start方法启动线程。线程启动后将 运行run方法。以下代码是使用threading模块创建线程。 ''' # coding:utf-8 # Python Bible - e23_1_1.py import threading #导入threading模块 class mythread(threading.Thread): #通过继承Thread创建类 def __init__(self, num): #定义初始化方法 threading.Thread.__init__(self) #调用父类的初始化方法 self.num = num def run(self): #重载run方法 print('I am ', self.num) t1 = mythread(1) #生成mythread对象 t2 = mythread(2) #生成mythread对象 t3 = mythread(3) #生成mythread对象 t1.start(); #运行线程1,实际上是运行run方法 t2.start(); #运行线程2 t3.start(); #运行线程3 ''' D:\CODE\PYTHON\Python_Bao3Dian3>python e23_1_1.py I am 1 I am 2 I am 3 '''
''' 除了通过继承threading.Thread创建类以外,还可以通过使用thread.Thread直接在线程中 运行函数。以下代码是使用threading.Thread直接创建线程。 ''' # encoding: UTF-8 # in Python 3.2.5 import threading # 导入threading 模块 def run(x,y): # 定义 run 函数 for i in range(x,y): print(i) t1 = threading.Thread(target = run, args = (15,20)) # 直接使用 Thread 附加函数, args 为函数参数 t1.start() # 运行线程 t2 = threading.Thread(target = run, args = (7,11)) # 直接使用 Thread 附加函数, args 为函数参数 t2.start() # 运行线程 ''' D:\CODE\PYTHON\Python_Bao3Dian3>python e23_1_1b.py 15 7 16 8 17 18 9 19 10 '''
# coding:UTF-8 # 23.1.2 Thread对象中的方法 ''' 1. join()方法 如果一个线程或函数在执行过程中调用另一个线程, 并且必须等待后一线程完成操作后才能 继续当前线程的执行, 那么在调用线程中可以使用被调用线程的join()方法.join()方法的原型如下. join([timeout]) timeout 可选参数, 单位为秒, 是线程运行的最长时间 ''' import threading # 导入threading模块 import time # 导入 time 模块 class Mythread(threading.Thread): # 通过继承Thread创建类 def __init__(self,id): # 初始化方法 threading.Thread.__init__(self) # 调用父类的初始化方法 self.id = id def run(self): # 重写run方法 x = 0 time.sleep(3) # 使用time模块中的sleep()方法让线程休眠3秒 print(self.id) def func1(): # 定义函数 t.start() # 运行线程 #t.join() for i in range(5): print(i) t = Mythread(182) func1() ''' # 到最后才有线程的输出, func1函数没有等待线程完成 D:\CODE\PYTHON\Python_Bao3Dian3>python e23_1_2a.py 0 1 2 3 4 182 # 把 t.join() 前的 # 去掉, 再次运行脚本。线程休眠3秒输出182,然后再输出0-4 D:\CODE\PYTHON\Python_Bao3Dian3>python e23_1_2a.py 182 0 1 2 3 4 '''
# coding:UTF-8 # 23.1.2 Thread对象中的方法 ''' 2. isAlive()方法 当线程创建后,可以使用Thread对象的isAlive方法查看线程是否运行。以下代码时使用Thread 对象的isAlive方法查看线程是否运行。 ''' import threading # 导入threading模块 import time # 导入time模块 class mythread(threading.Thread): # 通过继承Thread创建类 def __init__(self,id): # 初始化方法 threading.Thread.__init__(self) # 调用父类的初始化方法 self.id = id def run(self): # 重写run方法 time.sleep(5) print(self.id) t = mythread(1) # 生成mythread对象 def func(): # 定义函数 t.start() # 运行/启动线程 print('isAlive:%s' % t.isAlive()) # 打印线程状态 func() # 调用函数 ''' D:\CODE\PYTHON\Python_Bao3Dian3>python e23_1_2b.py isAlive:True # 从函数输出的线程状态 1 # 线程输出 '''
# coding:UTF-8 # 23.1.2 Thread对象中的方法 ''' 3. 线程名 线程名可以在类的初始化函数中定义,也可以使用Thread对象的setName方法设置。 使用Thread对象的getName方法可以获得线程名。 ''' import threading # 导入threading模块 class mythread(threading.Thread): # 通过继承Thread创建类 def __init__(self,threadname): threading.Thread.__init__(self,name = threadname) # 初始化线程名 def run(self): # 重写run方法 print(self.getName()) t1 = mythread('t1') # 类实例化,设置线程名 print(t1.getName()) # 调用getName方法获得线程名 t1.setName('T') # 调用setNa方法设置线程名 print(t1.getName()) t2 = mythread('t2') t2.start() print(t2.getName()) t2.setName('TT') print(t2.getName()) ''' D:\CODE\PYTHON\Python_Bao3Dian3>python e23_1_2c.py t1 T t2 t2 TT '''
# -*- coding:utf-8 -*- # file: threaddaemon.py # 23.1.2 Thread对象中的方法 ''' 4. daemon属性 在脚本运行过程中,如果主线程创建一个子线程,则当主线程退出时,会检验 子线程是否完成。如果子线程未完成,则主线程会等待子线程完成后再退出。如果想要主线程退出 时,不管子线程是否完成都随主线程退出,则可以通过设置Thread对象的daemon属性为True 来达到这种效果。以下代码是给Thread对象的daemon属性赋值为True,设置子线程随主线程结束而结束。 ''' import threading # 导入threading模块 import time class mythread(threading.Thread): def __init__(self,threadname): threading.Thread.__init__(self,name = threadname) self.sleeptime = 2 def run(self): time.sleep(self.sleeptime) print(self.getName()) def setSleeptime(self, time): self.sleeptime = time t1 = mythread('t1') t2 = mythread('t2') print('t1.daemon is %s' % t1.daemon ) t2.setSleeptime(10) t2.daemon = True def func1(): t1.start() print('func1 done') def func2(): t2.start() print('func2 done') func1() func2() ''' D:\CODE\PYTHON\Python_Bao3Dian3>python e23_1_2d.py t1.daemon is False func1 done func2 done t1 '''
''' A boolean value indicating whether this thread is a daemon thread (True) or not (False). This must be set before start() is called, otherwise RuntimeError is raised. Its initial value is inherited from the creating thread; the main thread is not a daemon thread and therefore all threads created in the main thread default to daemon = False. The entire Python program exits when no alive non-daemon threads are left. 当daemon被设置为True时,如果主线程退出,那么子线程也将跟着退出, 反之,子线程将继续运行,直到正常退出。 ''' import threading import time class myThread(threading.Thread): def __init__(self, threadname): threading.Thread.__init__(self, name=threadname) self.sleeptime = 2 def run(self): time.sleep(self.sleeptime) print(self.getName()) def setSleeptime(self, t): self.sleeptime = t def fun1(): t1.start() print("fun1 done") def fun2(): t2.start() print("fun2 done") t1=myThread("t1") t2=myThread("t2") t2.setSleeptime(10); t2.setDaemon(True) fun1() fun2() print("now u will see me") ''' D:\CODE\PYTHON\Python_Bao3Dian3>python tt.py fun1 done fun2 done now u will see me t1 '''
# -*- coding:utf-8 -*- # file: syn.py # 23.2 线程同步 ''' 23.2.1 简单的线程同步 使用Thread对象的Lock和RLock可以实现简单的线程同步. 如果某个数据在某一时刻只允许一个线程进行操作,则可以 将操作过程放在acquire方法和release方法之间. ''' import threading # 导入threading模块 import time class mythread(threading.Thread): def __init__(self,threadname): threading.Thread.__init__(self,name = threadname) def run(self): global x #lock.acquire() for i in range(3): x += 1 time.sleep(2) print(x) #lock.release() #lock = threading.RLock() t1 = [] for i in range(3): t = mythread(str(i)) t1.append(t) x = 0 for i in t1: i.start() ''' D:\CODE\PYTHON\Python_Bao3Dian3>python e23_2_1a.py 3 6 9 D:\CODE\PYTHON\Python_Bao3Dian3>python e23_2_1a.py 9 9 9 '''
# -*- coding:utf-8 -*- # 23.2 线程同步 # P_C.py ''' 23.2.2 使用条件变量保持线程同步 Python的Condition对象提供了对复杂线程同步的支持. 使用Condition对象可以在某些事件 触发后在处理数据. Condition对象除了具有acquire方法和release方法外, 还有wait方法, notify方法, notifyAll方法等用于条件处理的方法. 下面的P_C.py是使用Condition对象来实现著名的 生产者和消费者的关系. ''' import threading # 导入threading模块 class Producer(threading.Thread): # 定义生产者类 def __init__(self,threadname): threading.Thread.__init__(self,name = threadname) def run(self): global x con.acquire() # 调用con的acquire方法 if x == 1000000: con.wait() # 调用con的wait方法 #pass else: for i in range(1000000): x = x + 1 con.notify() # 调用con的notify方法 print(x) con.release() # 调用con的release方法 class Consumer(threading.Thread): # 定义生产者类 def __init__(self,threadname): threading.Thread.__init__(self,name = threadname) def run(self): global x con.acquire() if x == 0: con.wait() #pass else: for i in range(1000000): x = x -1 con.notify() print(x) con.release() con = threading.Condition() # 生成Condition对象 x = 0 p = Producer('Producer') # 生成生产者对象 c = Consumer('Consumer') # 生成消费者对象 p.start() c.start() p.join() # 等待p线程结束 c.join() print(x) ''' D:\CODE\PYTHON\Python_Bao3Dian3>python e23_2_2a.py 1000000 0 0 # 把使用Condition对象的语句删除. 运行修改后的脚本, 输出如下(每次输出可能不同) D:\Python27>python D:\CODE\PYTHON\Python_Bao3Dian3\ttb.py -29904 895935 895935 '''
import threading import time class Producer(threading.Thread): def run(self): global count while True: if con.acquire(): if count > 1000: con.wait() else: count = count+100 msg = self.name+' produce 100, count=' + str(count) print(msg) con.notify() con.release() time.sleep(1) class Consumer(threading.Thread): def run(self): global count while True: if con.acquire(): if count < 100: con.wait() else: count = count-3 msg = self.name+' consume 3, count='+str(count) print(msg) con.notify() con.release() time.sleep(1) count = 500 con = threading.Condition() def test(): for i in range(2): p = Producer() p.start() for i in range(5): c = Consumer() c.start() if __name__ == '__main__': test()