python 线程编程 Treading
记录时间:2019/4/23
问题:
- python运行程序和各个线程之间什么关系?
- 如何来实例化一个线程?如何运行一个线程?需要注意什么?
- 面向对象编程中如何定义一个线程?
- 如何在主线程中等待各个子线程完成?
- 如何设置守护线程?即主线程运行完之后守护线程自动退出?
- 线程之间如何进行最简单的标志位通讯?
- 线程中如何定义锁?多个锁如何来使用?
- 什么是信号量?如何定义信号量?在什么场景下会使用信号量?
- 队列如何使用?可以和线程之间产生什么互动?
解答:
1. python运行的主程序和各个线程之间什么关系?
python中的主程序作为 主线程,而在程序中定义地称为 子线程,多个线程并发执行。
2. 如何来实例化一个线程?如何运行一个线程?需要注意什么?
使用 mythread = threading.Thread( )来声明一个线程; 声明之后使用 .start()方法来启动这个进程; 需要注意,声明时参数必须用元祖的形式传入
- 使用 thread.Threading( )来声明一个线程
# 定义线程运行的函数 def run(n): print("task", n) time.sleep(2) print("task done",n) # 来实例化线程 t1 = threading.Thread(target=run, args=("t1",)) # args 必须以元祖的形式传入 # 启动线程 t1.start()
3. 面向对象编程中如何定义一个线程?
要定义一个线程,需要根据 Threading.Thread 作为父类来定义一个子类,在构造函数中将父类重构,并且定义 run() 成员函数,来说明当线程运行的程序。
- 定义 线程类
# 定义线程类 class MyThread(threading.Thread): # 构造函数 def __init__(self,n,sleep_time): super(MyThread, self).__init__() # 先来使用 super()完成父类的初始化 self.n = n self.sleep_time = sleep_time # 定义线程运行的程序 def run(self): print("running task", self.n) time.sleep(self.sleep_time) print("task done", self.n) # 线程类的实例化 t1 = MyThread("t1", 2) t2 = MyThread("t2", 4) # 线程对象的运行 t1.start() t2.start()
4. 如何在主线程中等待各个子线程完成?
使用 Thread.join() 成员函数,表示等待该线程执行完成再来执行下面的语句
- 使用 Thread.join() 成员函数来等待循环线程全部执行完成
# 初始化一个列表,来存储各个定义的线程,方便标记 obj_t=[] # 循环来启动线程 for i in range(50): t = threading.Thread(target=run, args=("t-{}".format(i),)) t.start() obj_t.append(t) # 一定会按照线程的执行顺序来等待线程执行完成 for i in obj_t: i.join()
5. 如何设置守护线程?即主线程运行完之后守护线程自动退出?
在实例化线程t之后,有个 t.setDaemon(True) 函数,在运行前调用,则默认作为主线程的守护线程,相当于主线程的仆人,主线程运行完成,则自动会退出这个守护线程,不论它执行到哪一步。
- setDaemon() 来设置守护线程
# 哪怕 run()函数运行很长时间,只要这个主线程退出了,则这个run()的线程一定会被退出 t = threading.Thread(target=run, args=("t-{}".format(i),)) t.setDaemon(True) t.start()
6. 线程之间如何进行最简单的标志位通讯?
来实例一个事件 e = threading.Event(), 然后在各个线程之间进行相互通信,相当于来设置一个全局变量,然后所有线程都可以检测到它的存在。
- threading.Event() 的用法?
# 来声明一个事件 event = threading.Event() # 设置这个事件的标志位 event.set() # 检测这个事件的标志位,如果被设置,则返回 1 event.is_set() # 清空这个事件的标志位 event.clear()
7. 线程中如何定义锁?多个锁如何来使用?
使用 lock = threading.Lock() 来实例化一个锁对象,然后就可以用它来开关了
- 使用 threading.Lock( ) 来防止他们之间的线程冲突
import threading # 在多线程之间定义锁,防止在处理共享数据时发生冲突错误,让其数据处理为原子操作 def run(): # 锁的获取 lock.acquire() global num num += 1 #锁的释放 lock.release() lock = threading.Lock() num = 1 for i in range(50): t = threading.Thread(target=run, args=()) t.start() print(num)
8. 什么是信号量?如何定义信号量?在什么场景下会使用信号量?
信号量相当于多把锁,因为线程共享一个代码块,所以,信号量规定一个时间内最多有n个代码块来访问执行这个代码块,使用 semaphore = threading.BoundedSemaphore(n) 来定义信号量,一次最多有n个可以来进行访问;有很多场景下可以使用信号量,比如 socket线程池,python默认会可以开无数个线程,但是线程多了必然会影响性能,所以,在这时候,我们可以通过信号量来规定其最大调用的线程个数
- 使用threading.BoundedSemaphore(n)
import threading, time def run(n): # 即最多有五个线程可以访问这个代码块 semaphore.acquire() time.sleep(10) print("run the thread: %s\n" % n) semaphore.release() if __name__ == '__main__': semaphore = threading.BoundedSemaphore(5) # 最多允许5个线程同时运行 for i in range(22): t = threading.Thread(target=run, args=(i,)) t.start() # 不断输出线程个数,当线程数threading.active_count()为1的时候,那么说明子线程全部运行完,还剩一个主线程 while threading.active_count() != 1: # 你可以看到一共有23个,然后每过1秒减少5个,直到还有最后一个主线程 print(threading.active_count()) else: print('----all threads done---')
9. 队列如何使用?可以和线程之间产生什么互动?
队列是在一个 queue模块 当中,q = queue.Queue(maxsize=10)来实例化一个队列,q.put()来入队,q.get()来出队;可以和线程一起来建立一个 生产者消费者模型,生产者一边生产,生产完了入队,消费者检测,如果存在则直接输出消费掉。注意,若为空,则q.get()会一直在这里等待。
- queue.Queue()
import threading import time import queue # 生成一个队列对象,最大值为 10 q = queue.Queue(maxsize=10) def Producer(name): count = 1 while True: # 生产完进入队列 q.put("骨头{}".format(count)) print("生产了骨头",count) count += 1 time.sleep(0.1) def Consumer(name): while True: # 若存在则直接输出 print("[{}]取到[{}]并且吃了它...".format(name, q.get())) time.sleep(1) p = threading.Thread(target=Producer, args=("Alex",)) c = threading.Thread(target=Consumer, args=("ChenRonghua",)) x = threading.Thread(target=Consumer, args=("XiaoHengheng",)) p.start() c.start() x.start()
本文介绍了Python中的线程编程,包括线程之间的关系、如何创建和运行线程、线程的等待与守护、线程间通信及同步机制,如锁、信号量和队列的应用。通过实例讲解了线程的生命周期和并发执行的细节。
2245

被折叠的 条评论
为什么被折叠?



