创建线程
import threading

threading中重要函数
active_count()
返回当前存活的线程类 Thread 对象。
current_thread()
返回当前对应调用者的控制线程的 Thread 对象。
get_ident()
返回当前线程的 “线程标识符”。它是一个非零的整数。
enumerate()
以列表形式返回当前所有存活的 Thread 对象。
main_thread()
返回主 Thread 对象。一般情况下,主线程是Python解释器开始时创建的线程。
settrace(func)
为所有 threading 模块开始的线程设置追踪函数。在每个线程的 run() 方法被调用前,func 会被传递给 sys.settrace() 。
setprofile(func)
为所有 threading 模块开始的线程设置性能测试函数。在每个线程的 run() 方法被调用前,func 会被传递给 sys.setprofile() 。
stack_size([size])
返回创建线程时用的堆栈大小。
重要功能
run()
用以表示线程活动的方法
start()
启动线程活动
join([time])
等待至线程中止
isAlive()
返回线程是否活动
getName()
返回线程名
setName()
设置线程名
守护线程
另外一个重要的入口参数是daemon,它的作用是设置线程是否为守护线程(后台线程)。守护线程有一个重要的特点是主线程(例子的main()线程)退出时,守护线程不管怎样都要跟主线程一起退出。
守护线程的目的与作用:

所以,我的理解是:当创建的子线程是无限循环的话,就应该设置为守护线程。随着主线程的退出,子线程被强制退出,保证了整个python程序正常地,完整地退出。
类下线程
将类的成员函数当做线程启动:
由于线程共享进程的资源,所以修改类中成员变量,可以影响到线程中对该成员变量的使用,所以不需要重新启动线程。
import os
from pathlib import Path
from time import sleep, time
from threading import Thread
from colorama import init, Fore, Back, Style
if "PYCHARM_HOSTED" in os.environ:
convert = False
strip = False
else:
convert = None
strip = None
init(convert=convert, strip=strip)
cur_pdir = Path(os.path.dirname(os.path.abspath(__file__)))
print("cur_pdir: ", cur_pdir)
class SomeClass(object):
def __init__(self, flag_polling=False):
# 轮询标志位 #
self.flag_polling = flag_polling
# 启动守护线程 #
self.start()
def start(self):
"""
开机即开启
:return:
"""
# 串口轮询线程
self.thread = self.openThread(self.get_status, args=())
def get_status(self):
"""
串口线程
:return:
"""
while True:
print(">>>")
print("flag_polling: ", self.flag_polling)
if self.flag_polling:
print(Fore.MAGENTA+"start to polling"+Style.RESET_ALL)
print()
sleep(0.1)
@staticmethod
def openThread(func, args=()):
thread = Thread(target=func, args=args)
thread.setDaemon(True)
thread.start()
return thread
if __name__ == '__main__':
sc = SomeClass()
index = 0
while True:
sleep(0.5)
if index == 10 * 5:
print(Back.CYAN+"i am going to change flag"+Style.RESET_ALL)
sc.flag_polling = True
index = index + 1
多线程队列Queue
概述
导入队列:
from queue import Queue
Queue队列遵循的是先进先出。
queue.Queue是进程内非阻塞队列,用于进程内的各函数模块或线程间通信。
q.put_nowait()
q.put_nowait()方法可以无阻碍地向队列中添加内容,如果队列已满则会立即报错,不会等待(即不会发生阻塞)。
q.get_nowait()
q.get_nowait()方法可以无阻碍地从队列中取出内容,如果队列是空的则也会直接报错,不会等待。
q.full()
判断队列是否是满的
q.empty()
判断队列是否是空的
q.qsize()
返回队列的大小
Queue提供了一个基本的FIFO容器,使用方法很简单Queue(maxsize=0),maxsize是个整数,指明了队列中能存放的数据个数的上限。一旦达到上限,插入会导致阻塞,直到队列中的数据被消费掉。如果maxsize小于或者等于0,队列大小没有限制。
q.clear()
清空队列
task_done()
意味着之前入队的一个任务已经完成。由队列的消费者线程调用。每一个get()调用得到一个任务,接下来的task_done()调用告诉队列该任务已经处理完毕。
如果当前一个join()正在阻塞,它将在队列中的所有任务都处理完时恢复执行(即每一个由put()调用入队的任务都有一个对应的task_done()调用)。
join()
阻塞调用线程,直到队列中的所有任务被处理掉。
只要有数据被加入队列,未完成的任务数就会增加。当消费者线程调用task_done()(意味着有消费者取得任务并完成任务),未完成的任务数就会减少。当未完成的任务数降到0,join()解除阻塞。