'''
在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()