python threading模块(全)

系统 1558 0

        一、线程与进程的介绍参考之前写的VC++的多线程与互斥对象:

 https://blog.csdn.net/Gordennizaicunzai/article/details/52268343

        二、python全局解析器锁(GIL)。

        python代码相对于其它语言在多线程效率上有个“先天性缺陷”——python有个虚拟机(又名解析器主循环)对代码进行执行控制,在解析器主循环中单位时间内只能有一个控制线在执行。意思是任意时刻只能有一个程序在运行,即使内存中有多个程序。python通过GIL对虚拟机进行访问:

        1、设置GIL。

        2、切换进一个线程去运行。

        3、执行下面操作之一:

                a. 指定数量的字节码指令。

                b. 线程主动让出控制权(可以调用time.sleep(0))来完成。

        4、把线程设置回睡眠状态(切换退出线程)。

        5、解锁GIL。

        6、重复1~5。

        对效率要求非常高的python开发中,倾向于这样设计:

        IO密集型(不用CPU)——多线程

        计算密集型(用CPU)——多进程

        三、Threading模块的对象。

对象 描述
Thread 表示一个执行线程的对象。
Lock 锁原语对象(和thread模块中的锁一样)。
Rlock 可重入锁对象,使单一线程可以(再次)获得已持有的锁(递归锁)。
Condition 条件变量对象,使得一个线程等待另一个线程满足特定的“条件”,比如改变状态或某个数据值。
Event 条件变量的通用版本,任意数量的线程等待某个事件的发生,在该事件发生后所有线程将被激活。
Semaphore 为线程间共享的有限资源提供了一个“计数器”,如果没有可用资源时会被阻塞。
BoundedSemaphore 与Semahore相似,不过它不允许超过初始值。
Timer 与Thread相似,不过它要在运行前等待一段时间。
Barrier 创建一个“障碍”,必须达到指定数量的线程后才可以继续。

        3.1、Thread类。

属性或方法 描述
name 线程名,可以用直接赋值进行修改,如Thread.name = 'T1'。
ident 线程的标识符。
daemon 布尔标志,True为守护线程,False则不是,可以直接赋值,如Thread.daemon = True。
_init_(group=None, tatget=None, name=None, args=(),
kwargs={}, verbose=None, daemon=None)
实例化一个线程对象,需要有一个可调用的target,以及其参数args(传元祖等iterable)或kwargs。还可以传递name或group参数,不过后者还未实现。此外,verbose标志也是可以接受的。而daemon的值将会设定thread.daemon属性/标志。
start() 开始执行该线程。
run() 定义线程功能的方法(通常在子类中被应用开发者重写)。
join(timeout=None) 直至启动的线程终止之前一直挂起:除非给出了timeout(秒),否则会一直阻塞。自旋锁。
is_alive() 布尔标志,表示这个线程是否还活着。
            
              >>> import threading
>>> import time
>>> 
>>> def thread1(tickets):
	if tickets <= 0:
		print("输入的票数不能小于等于0")
		return False
	while tickets > 0:
		print("thread1 sell ticket : %d" % tickets)
		tickets -= 1
		time.sleep(1)
	return True

>>> t1 = threading.Thread(target=thread1,args=(50,))
>>> t1

              
                
>>> t1.name
'Thread-4'
>>> t1.name = 'T1'
>>> t1

                
                  
>>> t1.name
'T1'
>>> t1.daemon
False
>>> t1.daemon = True
>>> t1.daemon
True
>>> t1.is_alive()
False
>>> t1.start()
thread1 sell ticket : 50
>>> 
thread1 sell ticket : 49
thread1 sell ticket : 48
thread1 sell ticket : 47
thread1 sell ticket : 46
thread1 sell ticket : 45t1.is_alive()
True

>>> thread1 sell ticket : 44
thread1 sell ticket : 43
thread1 sell ticket : 42
thread1 sell ticket : 41
thread1 sell ticket : 40
thread1 sell ticket : 39
thread1 sell ticket : 38
print('Y')
Y
>>> thread1 sell ticket : 37
thread1 sell ticket : 36
thread1 sell ticket : 35
thread1 sell ticket : 34
thread1 sell ticket : 33
thread1 sell ticket : 32
t1.join()  # 启用join,下面将一直阻塞,直到T1运行结束
thread1 sell ticket : 31
thread1 sell ticket : 30
thread1 sell ticket : 29
thread1 sell ticket : 28
thread1 sell ticket : 27
thread1 sell ticket : 26
thread1 sell ticket : 25
thread1 sell ticket : 24
thread1 sell ticket : 23
thread1 sell ticket : 22
thread1 sell ticket : 21
thread1 sell ticket : 20
thread1 sell ticket : 19
thread1 sell ticket : 18
thread1 sell ticket : 17
thread1 sell ticket : 16
thread1 sell ticket : 15
thread1 sell ticket : 14
thread1 sell ticket : 13
thread1 sell ticket : 12
thread1 sell ticket : 11
thread1 sell ticket : 10
thread1 sell ticket : 9
thread1 sell ticket : 8
thread1 sell ticket : 7
thread1 sell ticket : 6
thread1 sell ticket : 5
thread1 sell ticket : 4
thread1 sell ticket : 3
thread1 sell ticket : 2
thread1 sell ticket : 1
>>> print('Y')
Y
>>> 
                
              
            
          

 

        3.2、Lock类。

        锁有且只有两种状态:锁定和未锁定。获得锁函数用acquire()、 释放锁函数用release()。当多线程争夺锁时,允许第一个获得锁的线程进入临界区,并执行代码,其它后面到达的所有线程都将被阻塞,直到第一个获得锁的那个线程执行结束,退出临界区,并释放锁后,其它等待的线程才可以获得锁并进入临界区。注意,那些被阻塞的线程是没有顺序的,并不是先到先得,而是不确定的。

未加锁:

            
              >>> import threading
>>> import time
>>> 
>>> tickets = 50
>>> def thread1():
	global tickets  # 全局变量
	while tickets > 0:
		print("thread1 sell ticket : %d\r\n" % tickets)
		tickets -= 1
		time.sleep(0.1)
	return True

>>> def thread2():
	global tickets  # 全局变量
	while tickets > 0:
		print("thread2 sell ticket : %d\r\n" % tickets)
		tickets -= 1
		time.sleep(0.1)
	return True

>>> threads = []
>>> t1 = threading.Thread(target=thread1)
>>> threads.append(t1)
>>> t2 = threading.Thread(target=thread2)
>>> threads.append(t2)
>>> 
>>> for i, t in enumerate(threads):
	t.start()
	time.sleep(0.1)

	
thread1 sell ticket : 50


thread2 sell ticket : 49

thread1 sell ticket : 49



>>> thread2 sell ticket : 47

thread1 sell ticket : 47



thread2 sell ticket : 45

thread1 sell ticket : 45



thread2 sell ticket : 43

thread1 sell ticket : 43



thread2 sell ticket : 41

thread1 sell ticket : 41
......
            
          

加锁:

            
              >>> tickets = 20
>>> lock = threading.Lock()
>>> 
>>> def thread1():
	global tickets  # 全局变量
	while tickets > 0:
		lock.acquire()
		tickets -= 1
		print("thread1 sell ticket : %d\n" % tickets)
		lock.release()
		time.sleep(0.2)
	return True

>>> def thread2():
	global tickets  # 全局变量
	while tickets > 0:
		lock.acquire()
		tickets -= 1
		print("thread2 sell ticket : %d\n" % tickets)
		lock.release()
		time.sleep(0.2)
	return True

>>> threads = []
>>> t1 = threading.Thread(target=thread1)
>>> threads.append(t1)
>>> t2 = threading.Thread(target=thread2)
>>> threads.append(t2)
>>> 
>>> for i, t in enumerate(threads):
	t.start()

	
thread1 sell ticket : 19
>>> 
thread2 sell ticket : 18

thread1 sell ticket : 17

thread2 sell ticket : 16

thread1 sell ticket : 15

thread2 sell ticket : 14

thread1 sell ticket : 13

thread2 sell ticket : 12

thread1 sell ticket : 11

thread2 sell ticket : 10

thread1 sell ticket : 9

thread2 sell ticket : 8

thread1 sell ticket : 7

thread2 sell ticket : 6

thread1 sell ticket : 5

thread2 sell ticket : 4

thread1 sell ticket : 3

thread2 sell ticket : 2

thread1 sell ticket : 1

thread2 sell ticket : 0
            
          

        3.3、RLock类。

        RLock和Lock没多大区别。RLock为可重入锁,可以由同一线程多次获取。在内部,除了原始锁使用的锁定/解锁状态之外,它还使用“拥有线程”和“递归级别”的概念。在锁定状态下,某些线程拥有锁; 在解锁状态下,没有线程拥有它。申请和释放必须成对出现:

            
              >>> import threading
>>> rLock = threading.RLock()
>>> rLock.acquire()
True
>>> rLock.acquire()
True
>>> rLock.acquire()
True
>>> rLock.release()
>>> rLock.release()
>>> rLock.release()
>>> rLock.release()
Traceback (most recent call last):
  File "
              
                ", line 1, in 
                
                  
    rLock.release()
RuntimeError: cannot release un-acquired lock
>>> 
>>> # 说明RLock的acquire()与release()必须成对出现。
                
              
            
          
            
              >>> lock.acquire()
True
>>> lock.acquire()



lock.release()
lock.release()
lock.release()
# 已经产生了死锁,没有反应了
lock.release()
            
          

        3.4、 Condition类(更高级的锁)

        

        线程的挂起与阻塞:

  挂起:是因为我们需要进行调度然后认为的暂停某个线程的执行,我们也会主动放下线程实现线程的继续运行

  阻塞:多半是被动的,因为资源访问的竞争,或是线程冲突。

  阻塞的线程挂起放下后依然是阻塞的。

  可以把Condiftion理解为一把高级的锁,它提供了比Lock, RLock更高级的功能,允许我们能够控制复杂的线程同步问题。

  threadiong.Condition在内部维护一个锁对象(默认是RLock),可以在创建Condigtion对象的时候把锁对象作为参数传入。

condition方法:

  1.acquire():线程获得锁

  2.release():释放锁

  3.wait():wait方法释放内部所占用的琐,同时线程被挂起,直至接收到通知被唤醒或超时(如果提供了timeout参数的话)。当线程被唤醒并重新占有琐的时候,程序才会继续执行下去。。

  4.notify():唤醒一个挂起的线程(如果存在挂起的线程)。注意:notify()方法不会释放所占用的琐。

        5.notifyAll():唤醒所有挂起的线程(如果存在挂起的线程)。注意:这些方法不会释放所占用的琐。

  捉迷藏:

            
              >>> import threading, time
>>> 
>>> class Seeker(threading.Thread):
	def __init__(self, cond, name):
		threading.Thread.__init__(self)
		self.cond = cond
		self.name = name
	def run(self):
		time.sleep(1)  # 1.确保seeker晚于hider开始执行
		print('1\n')
		self.cond.acquire()  # 4. seeker申请锁
		print ('我把眼睛蒙上了\n')
		self.cond.notify()  # 5.蒙上眼后通知hider,hider线程此时被唤醒并试图获取锁,锁将在seeker身上,所以hider会被阻塞,seeker继续往下
		self.cond.wait()  # 6. seeker锁被释放并且挂起,hider就获取锁开始继续往下运行了
		print('2\n')
		print ('我找到你了\n')
		self.cond.notify()  # 9.找到了之后通知hider,hider意图获取锁但不行所以被阻塞,seeker往下
		self.cond.release()  # 10.seeker释放锁,以便被通知的hider可以或得到锁
		print('3\n')
		print ('我赢了\n')

		
>>> 
>>> class Hider(threading.Thread):
	def __init__(self, cond, name):
		threading.Thread.__init__(self)
		self.cond = cond
		self.name = name
	def run(self):
		self.cond.acquire()  # 2.hider获取锁
		self.cond.wait()  # 3.hider被挂起然后释放锁
		print('4\n')
		print ('我已经藏好了\n')
		self.cond.notify()  # 7.藏好后通知seeker,seeker意图获取锁,但是锁在hider身上所以seeker被阻塞
		self.cond.wait()  # 8.hider被挂起,释放锁,seeker获取锁,seeker继续往下运行
		print('5\n')
		self.cond.release()# 11. 在此句之前一点,seeker释放了锁(#10),hider得到锁,随即这句hider释放锁
		print ('被你找到了\n')

		
>>> 
>>> cond = threading.Condition()
>>> seeker = Seeker(cond, 'seeker')
>>> hider = Hider(cond, 'hider')
>>> threads = []
>>> threads.append(seeker)
>>> threads.append(hider)
>>> for i, t in enumerate(threads):
	t.start()

	
>>> 1

我把眼睛蒙上了

4

我已经藏好了

2

我找到你了

5
3


被你找到了
我赢了



>>> 
            
          

        3.5、Event类(利用标志位实现的锁)

        

        Event实现与Condition类似的功能,不过比Condition简单一点。它通过维护内部的标识符来实现线程间的同步问题。

        1.Event.wait() : 堵塞线程,直到Event对象内部标识位被设为True或超时(如果提供了参数timeout)。

        2.Event.clear() : 将标志位置于false状态。

        3.Event.set() : 设置标志位为true

        4.Event.isSet() : 判断标志位状态

        用Event模拟红绿灯: 

            
              Python 3.7.4 (tags/v3.7.4:e09359112e, Jul  8 2019, 20:34:20) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> 
>>> import threading
>>> import time
>>> 
>>> def light(event):
	print('线程阻塞中,启动线程请输入[true]')
	event.wait()  # 阻塞线程,直到Event对象内部的标志位置为True
	counts = 0
	while True:
		event.clear()
		print('the light is red')
		time.sleep(6)
		if counts < 5:
			event.set()
		else:
			event.wait()
			break
		print('the light is green')
		time.sleep(4)
		print('the light is yellow')
		time.sleep(2)
		counts += 1

		
>>> 
>>> def car(event):
	event.wait()  # 阻塞线程,直到Event对象内部的标志位置为True
	while True:
		if event.isSet():
			print('green or yellow is on ,let`s go!')
			time.sleep(2)
		else:
			print('red in on, we must stop!')
			time.sleep(2)

			
>>> 
>>> event = threading.Event()
>>> threads = []
>>> t1 = threading.Thread(target=light,args=(event,))
>>> threads.append(t1)
>>> t2 = threading.Thread(target=car,args=(event,))
>>> threads.append(t2)
>>> for i, t in enumerate(threads):
	t.start()

	
>>> 线程阻塞中,启动线程请输入[true]

>>> start = input
>>> start = input()
true
>>> start
'true'
>>> if start == 'true':
	event.set()

	
green or yellow is on ,let`s go!the light is red
>>> 

red in on, we must stop!
red in on, we must stop!
the light is greengreen or yellow is on ,let`s go!

green or yellow is on ,let`s go!
the light is yellowgreen or yellow is on ,let`s go!

the light is redred in on, we must stop!

red in on, we must stop!
red in on, we must stop!
the light is green
green or yellow is on ,let`s go!
green or yellow is on ,let`s go!
the light is yellow
green or yellow is on ,let`s go!
the light is red
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
the light is green
green or yellow is on ,let`s go!
green or yellow is on ,let`s go!
the light is yellow
green or yellow is on ,let`s go!
the light is red
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
the light is green
green or yellow is on ,let`s go!
green or yellow is on ,let`s go!
the light is yellow
green or yellow is on ,let`s go!
the light is red
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
the light is green
green or yellow is on ,let`s go!
green or yellow is on ,let`s go!
the light is yellow
green or yellow is on ,let`s go!
the light is red
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!
red in on, we must stop!

            
          

        3.6、Semaphore([value])类(信号量)

        values是一个内部计数,values默认是1,如果小于0,则会抛出 ValueError 异常,可以用于控制线程数并发数。

        信号量是最古老的同步原语之一。它是一个计数器,当资源消耗时递减,当资源释放时递增。你可以认为信号量代表它们的资源可用或不可用。信号量比锁更加灵活,因为可以有多个线程共用一个资源的一个实例。

        信号量实际上就相当于一个计算器:

        acquire([blocking]),计数器加1;
        release(),计数器减1;

        3.7、BoundedSemaphore([value])类(更安全的信号量)

        BoundedSemaphore同Semaphore,不同的是BoundedSemaphore计数器的值永远不会超过它的初始值,它自动防止信号量释放的次数多于获得的次数,所以BoundedSemaphore更安全。

        信号量控制某个时间段内线程数量:

            
              >>> import threading
>>> import time
>>> 
>>> MAX_COUNTS = 3
>>> nums = threading.BoundedSemaphore(MAX_COUNTS)
>>> 
>>> def count(n):
	print('\nacquire time: %s' % time.ctime())
	time.sleep(5)
	nums.release()
	print('\n%d release time: %s' % (n, time.ctime()))

	
>>> for i in range(MAX_COUNTS*2):
	nums.acquire()
	t=threading.Thread(target=count, args=(i,))
	t.start()
	print('\n%s start' % t.name)

	
True

acquire time: Sat Aug 24 23:09:04 2019
Thread-1 start

True

acquire time: Sat Aug 24 23:09:04 2019
Thread-2 start

True

Thread-3 start
acquire time: Sat Aug 24 23:09:04 2019


0 release time: Sat Aug 24 23:09:09 2019True
1 release time: Sat Aug 24 23:09:09 2019
2 release time: Sat Aug 24 23:09:09 2019




Thread-4 start
acquire time: Sat Aug 24 23:09:09 2019

True

Thread-5 start
acquire time: Sat Aug 24 23:09:09 2019

True

Thread-6 start
acquire time: Sat Aug 24 23:09:09 2019

>>> 
3 release time: Sat Aug 24 23:09:14 2019

4 release time: Sat Aug 24 23:09:14 2019

5 release time: Sat Aug 24 23:09:14 2019

            
          

        3.8、Timer类

        threading.Timer是threading.Thread的子类,可以在指定时间间隔后执行某个操作。通过调用start()方法,启动计时器,就像使用线程一样。通过调用cancel()方法可以停止计时器(在其动作开始之前,只有在计时器仍处于等待阶段时才有效。)。

            
              >>> def fun1():
	print("%s I'm fun1" % time.ctime())

	
>>> def fun2():
	print("%s I'm fun2" % time.ctime())

	
>>> threads = []
>>> t1 = threading.Thread(target=fun1)
>>> threads.append(t1)
>>> t2 = threading.Timer(5, fun2)  # 5s后运行
>>> threads.append(t2)
>>> 
>>> for i, t in enumerate(threads):
	t.start()

	
Sat Aug 24 23:22:39 2019 I'm fun1
>>> 
Sat Aug 24 23:22:44 2019 I'm fun2
            
          

        3.9、 Barrier类

        Barrier类是设置了一个线程数量障碍,当等待的线程到达了这个数量就会唤醒所有的等待线程,可用于并发初始化等场景。

 class Barrier(builtins.object)
 |   Barrier(parties, action=None, timeout=None)  parties障碍要求的线程数量,action是一个可调用的函数,timeout是wait方法未指定时超时的默认值。
 |  
 |  Implements a Barrier.实现了一个障碍。
 |  
 |  Useful for synchronizing a fixed number of threads at known synchronization
 |  points.  Threads block on 'wait()' and are simultaneously awoken once they
 |  have all made that call.用于在已知同步点同步固定数量的线程。线程阻塞在'wait()'上,并在所有线程都发出该调用后同时被唤醒。
 |  
 |  Methods defined here:
 |  
 |   __init__(self, parties, action=None, timeout=None)
 |      Create a barrier, initialised to 'parties' threads.
 |      
 |      'action' is a callable which, when supplied, will be called by one of
 |      the threads after they have all entered the barrier and just prior to
 |      releasing them all. If a 'timeout' is provided, it is used as the
 |      default for all subsequent 'wait()' calls.“action”是一个可调用的函数,当它被提供时,其中一个线程将在它们全部进入屏障并在释放它们之前调用它。如果提供了“timeout”,它将作为所有后续“wait()”调用的默认值。
 |  
 |   abort(self)
 |      Place the barrier into a 'broken' state.将障碍设置为“破碎”状态。
 |      
 |      Useful in case of error.  Any currently waiting threads and threads
 |      attempting to 'wait()' will have BrokenBarrierError raised.在出错时有用。任何当前正在等待的线程和试图“wait()”的线程都将引发breakbarriererror异常,直到reset方法来恢复障碍。
 |  
 |   reset(self)
 |      Reset the barrier to the initial state.将障碍重置为初始状态,重新开始拦截,相当于电脑的重启按键。
 |      
 |      Any threads currently waiting will get the BrokenBarrier exception
 |      raised.当前等待的任何线程都将引发BrokenBarrierError异常。
 |  
 |   wait(self, timeout=None)
 |      Wait for the barrier.当前线程进入阻塞状态。
 |      
 |      When the specified number of threads have started waiting, they are all
 |      simultaneously awoken. If an 'action' was provided for the barrier, one
 |      of the threads will have executed that callback prior to returning.
 |      Returns an individual index number from 0 to 'parties-1'.当开始等待的线程数量达到指定数量时,它们都被同时唤醒。如果为障碍提供了一个“action”,其中一个线程将在返回之前执行该回调。
返回从0到“parties-1”的单个索引号。timeout:如果等待超时,则引发BrokenBarrierError异常。

 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
 |  
 |  broken
 |      Return True if the barrier is in a broken state.
 |  
 |   n_waiting
 |      Return the number of threads currently waiting at the barrier.返回当前等待的线程数
 |  
 |   parties
 |      Return the number of threads required to trip the barrier.返回通过障碍所需的线程数

            
              >>> def fun(barrier:threading.Barrier, n:int):
	print("n_waiting%d--%s\n" % (barrier.n_waiting, time.ctime()))
	try:
		if n < 3:
			barrier.wait(1)  # 设置超时时间1s,然后引发BrokenBarrierError异常,异常被except立刻捕获,后面的语句不会被执行
		else:
			if n == 5:
				barrier.reset()  # 重启障碍
				print('******barrier had reset******')
			b = barrier.wait()
			print('after barrier %s\n' % b)
	except threading.BrokenBarrierError:
		print('Broken barrier in %s--%s\n' % (threading.current_thread(), time.ctime()))

		
>>> barrier = threading.Barrier(3)
>>> for i in range(1,15):
	threading.Event().wait(1)  # 延迟1s
	threading.Thread(target=fun,args=(barrier,i),name='Barrier%d' % i).start()

	
False
n_waiting0--Sun Aug 25 12:44:10 2019

False
Broken barrier in 
              
                --Sun Aug 25 12:44:12 2019
n_waiting0--Sun Aug 25 12:44:12 2019


Broken barrier in 
                
                  --Sun Aug 25 12:44:12 2019

False
n_waiting0--Sun Aug 25 12:44:13 2019

Broken barrier in 
                  
                    --Sun Aug 25 12:44:13 2019

False
n_waiting0--Sun Aug 25 12:44:14 2019

Broken barrier in 
                    
                      --Sun Aug 25 12:44:14 2019

False
n_waiting0--Sun Aug 25 12:44:15 2019

******barrier had reset******
False
n_waiting1--Sun Aug 25 12:44:16 2019

False
n_waiting2--Sun Aug 25 12:44:17 2019

after barrier 2
after barrier 0
after barrier 1



False
n_waiting0--Sun Aug 25 12:44:18 2019

False
n_waiting1--Sun Aug 25 12:44:19 2019

False
n_waiting2--Sun Aug 25 12:44:20 2019

after barrier 2
after barrier 0
after barrier 1



False
n_waiting0--Sun Aug 25 12:44:21 2019

False
n_waiting1--Sun Aug 25 12:44:22 2019

False
n_waiting2--Sun Aug 25 12:44:23 2019

after barrier 2
after barrier 1
after barrier 0



False
n_waiting0--Sun Aug 25 12:44:24 2019
>>> 
                    
                  
                
              
            
          

        四、Threading模块的其它一些函数

        4.1、active_count() 

        返回当前活动的Thread对象个数,返回的个数中包含主线程。

            
              >>> counts = threading.active_count()
>>> counts
3
>>> 
            
          

        4.2、enumerate()

        返回当前活动的Thread对象列表。

            
              >>> threads = threading.enumerate()
>>> threads
[<_MainThread(MainThread, started 3208)>, 
              
                , 
                
                  ]
>>> 
                
              
            
          

        

        4.3、current_thread

        返回当前的Thread对象。

            
              >>> thread = threading.current_thread
>>> thread

              
                
>>> 
              
            
          

 


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论