0x00:thread模块

函数 / 方法 描述
thread 模块的函数
start_new_thread(function,args,kwargs=None) 派生一个新的线程,使用给定的args和可选的 kwargs 来执行 function
allocate_lock() 分配LockType 锁对象
exit() 线程退出指令
LockType 锁对象的方法
acquire(wait=None) 尝试获取锁对象
locked() 如果获取了锁对象则返回True,否则返回 False
release() 释放锁
  1. import _thread # 导入线程模块
  2. from time import ctime,sleep #导入时间戳和睡眠模块
  3. loops = [4,2] #把常量放到列表中
  4. def loop(nloop,nsec,lock): #定义 loop 函数
  5. print("start loop",nloop , 'at:' , ctime()) # 打印开始 loop
  6. sleep(nsec) #睡眠 nesc 秒
  7. print('aa', nloop , 'dont at:' ,ctime()) # 打印 loop nloop
  8. lock.release()
  9. def main(): # 定义main 函数z
  10. print('strting at: ', ctime()) # 打印开始的事件
  11. locks = [] #定义锁的列表
  12. nloops = range(len(loops)) # 获取 locks列表的长度
  13. for i in nloops: # 定义for循环
  14. lock = _thread.allocate_lock() # 分配locks锁的对象
  15. lock.acquire() # 尝试获取锁 lock的对象, 一旦锁被锁上后,就把锁添加到列表中
  16. locks.append(lock) #把锁添加到 lock列表中
  17. for i in nloops: # 创建循环用于派生线程
  18. _thread.start_new_thread(loop, (i, loops[i],locks[i])) # 这个循环会调用loop 函数, 传递循环信号、睡眠时间以及用于该线程锁的几个参数
  19. for i in nloops: # 定义一个循环
  20. while locks[i].locked(): #如果获取了锁的对象,就返回True,不然就是flase
  21. pass
  22. print('all Done at: ',ctime())
  23. if __name__ == '__main__':
  24. main() #调用 main 函数

运行结果:

  1. E:\Python3\python3.exe E:/pythonProject/thred线程模块.py
  2. strting at: Wed Jul 28 22:57:27 2021
  3. start loop 1 at: Wed Jul 28 22:57:27 2021
  4. start loop 0 at: Wed Jul 28 22:57:27 2021
  5. aa 1 dont at: Wed Jul 28 22:57:29 2021
  6. aa 0 dont at: Wed Jul 28 22:57:31 2021
  7. all Done at: Wed Jul 28 22:57:31 2021

注意事项
_thread对于进程何时退出没有任何控制。当主线程结束时,所有其他线程也都强制结束。不会发出警告或者进行适当的清理。因而python多线程一般使用较为高级的threading模块,它提供了完整的线程控制机制以及信号量机制。

0x01:threading 模块

对象 描述
Thread 表示一个执行线程的对象
Lock 锁原语对象
RLokc 可重入锁对象,使得一个线程等待另一个线程满足特定的条件,比如改变状态或者某个值
Condition 条件变量对象,使用一个线程等待另一个线程满足某个事件的发送,在该事件发生后,线程将被激活
Event 条件变量的通用版本,任意数量的线程等待某个事件的发生,在该事件发生后,线程将被激活
Semaphore 为线程间共享提供了一个计数器,如果没有可用资源会被阻塞
BoundedSemaphore 与Semaphore类似,不过它不允许超过初始值
Timer 与Thread 相似,不过他要在运行前等待一段时间
Barrier 创建一个障碍,必须达到指定数量的线程后才可以继续
函数 / 方法 描述
thread 对象数据属性
name 线程名
ident 线程的标识符
daemon 布尔标志,表示这个线程是否是守护线程
Thread 对象方法
init(group=None,target=None,name=None,args=None,kwargs=None,daemom) 实例化一个线程对象,需要一个可以调用的 target ,以及其参数 args 或 kwargs
strat() 开始执行该线程
run() 定义线程的方法
join(timeout=None) 直至启动的线程终止之前一直挂起,除非给出了timeout秒,否则会一直阻塞
getName() 返回线程名
setName() 设置线程名
isAlivel/ is_alive() 布尔标志,标志这个线程是否存活
isDaemmon(0 如果是守护线程,返回True, 否则返回 false
setDaemmon() 把线程的守护标志设置为布尔值(必须在线程开始之前调用)

(1)创建一个 thread的实例,传给他一个函数

在这个例子中,我们只是把Thread 类实例化,然后将函数(及其参数)传递进去。当线程开始执行时,函数也会执行。

  1. import threading # 导入 theading 模块
  2. from time import ctime,sleep # 导入时间、睡眠模块
  3. loops = [4,2] # 定义一个列表,睡眠的时间
  4. def loop(nloop,nesc): # 创建一个函数
  5. print("start loo", nloop ,'at:',ctime())
  6. sleep(nesc) # 睡眠 nesc 秒
  7. print("start loo", nloop ,'done at:',ctime())
  8. def main(): # 定义 一个 main 主函数
  9. print("start at:",ctime()) # 打印 开始的到时间
  10. threads = [] # 创建一个空列表
  11. nloops = range(len(loops)) # nloops 等于 0,1
  12. for i in nloops: # 创建一个 for 循环 ,取 nloops的值
  13. t = threading.Thread(target=loop,args=(i, loops[i])) # 创建一个执行线程的对象,传给它的一个函数
  14. threads.append(t) # 把线程的执行对象添加 theands 列表中
  15. for i in nloops: # 创建一个 for 循环
  16. threads[i].start() # 开始执行线程
  17. for i in nloops: # 创建一个 for 循环
  18. threads[i].join() # 为每个子线程 调用join方法,等待线程结束
  19. print("all Done at:",ctime()) # 打印输出语句
  20. if __name__ =='__main__':
  21. main()

join()方法等待线程结束,或者在提供了超时时间的情况下,达到超时时间。 join方法不需要调用,一旦线程开始,就会立即执行,知道给定的函数完成后退出。

(2)创建thread的实例,传给它一个可以调用的类实例

在创建线程时,与传入函数相似的一个方法就是传入一个可以调用的类的实例用于线程执行。 这种可调用的类包含一个执行环境,从一个函数或者从一组函数中选择而言,有更好的灵活性。

  1. import threading # 导入 theading 模块
  2. from time import ctime,sleep # 导入时间、睡眠模块
  3. loops = [4,2] # 定义一个列表,睡眠的时间
  4. class TheadFunc(object): # 创建一个类
  5. def __init__(self,func,args,name=''): #初始化 init ,实例化一个对象
  6. self.name = name # 赋值
  7. self.func = func
  8. self.args = args
  9. def __call__(self): #使用call方法,回调函数
  10. self.func(*self.args)
  11. def loop(nloop,nsec): #定义一个函数
  12. print("start loop", nloop, 'at:',ctime())
  13. sleep(nsec) # 定义睡眠得时间
  14. print("sloop", nloop, 'done at:',ctime())
  15. def main(): # 定义一个main 函数
  16. print("starting at:",ctime())
  17. threads = [] # 创建一个列表
  18. nloops = range(len(loops)) # 复制一个range,子线程数量
  19. for i in nloops:
  20. t = threading.Thread(
  21. target=TheadFunc(loop, (i, loops[i]),loop.__name__)) # 实例化线程的 Thread 对象, 这个很有意思
  22. threads.append(t)
  23. for i in nloops:
  24. threads[i].start() # 开其线程
  25. for i in nloops:
  26. threads[i].join() # 等待线程结束
  27. print("all DONE at:",ctime())
  28. if __name__ =='__main__':
  29. main()

(3)派生 Thread 的子类,并创建子类的实例

  1. import threading # 导入 theading 模块
  2. from time import ctime,sleep # 导入时间、睡眠模块
  3. loops = [4,2] # 定义一个列表,睡眠的时间
  4. class MyThread(threading.Thread): #创建一个 Thread子类
  5. def __init__(self,func,args,name=""): #初始化 init ,实例化一个对象
  6. threading.Thread.__init__(self)
  7. self.name = name
  8. self.func = func
  9. self.args = args
  10. def run(self): # 运行func这个函数
  11. self.func(*self.args)
  12. def loop(nloop,nesc):
  13. print("start loop", nloop, 'at:',ctime())
  14. sleep(nesc) # 定义睡眠得时间
  15. print("sloop", nloop, 'done at:',ctime())
  16. def main():
  17. print("starting at:",ctime())
  18. threads = [] # 创建一个列表
  19. nloops = range(len(loops)) # 复制一个range,子线程数量
  20. for i in nloops:
  21. t = MyThread(loop, (i, loops[i]),loop.__name__) # 实例化线程的 Thread 对象, 这个很有意思
  22. threads.append(t)
  23. for i in nloops:
  24. threads[i].start() # 开其线程
  25. for i in nloops:
  26. threads[i].join() # 等待线程结束
  27. print("all DONE at:",ctime())
  28. if __name__ =='__main__':
  29. main()