线程,有时被称为轻量进程,是程序执行流的最小单元。一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程不拥有私有的系统资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
线程是程序中一个单一的顺序控制流程。进程内有一个相对独立的、可调度的执行单元,是系统独立调度和分派cpu的基本单位指令运行时的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。Python多线程用于I/O *** 作密集型的任务,如SocketServer网络并发,网络爬虫。
现代处理器都是多核的,几核处理器只能同时处理几个线程,多线程执行程序看起来是同时进行,实际上是cpu在多个线程之间快速切换执行,这中间就涉及到上下问切换,所谓的上下文切换就是指一个线程Thread被分配的时间片用完了之后,线程的信息被保存起来,cpu执行另外的线程,再到cpu读取线程Thread的信息并继续执行Thread的过程。
线程模块
Python的标准库提供了两个模块:_thread和threading。_thread 提供了低级别的、原始的线程以及一个简单的互斥锁,它相比于 threading 模块的功能还是比较有限的。threading模块是_thread模块的替代,在实际的开发中,绝大多数情况下还是使用高级模块threading,因此本书着重介绍threading高级模块的使用。
Python创建Thread对象语法如下:
import threading threading.Thread(target=None, name=None, args=())
主要参数说明:
target 是函数名字,需要调用的函数。
name 设置线程名字。
args 函数需要的参数,以元祖( tuple)的形式传入
Thread对象主要方法说明:
run(): 用以表示线程活动的方法。
start():启动线程活动。
join(): 等待至线程中止。
isAlive(): 返回线程是否活动的。
getname(): 返回线程名。
setname(): 设置线程名。
Python中实现多线程有两种方式:函数式创建线程和创建线程类。
第一种创建线程方式:
创建线程的时候,只需要传入一个执行函数和函数的参数即可完成threading.Thread实例的创建。下面的例子使用Thread类来产生2个子线程,然后启动2个子线程并等待其结束,
import threading
import time,random,math
# IDx 循环次数
def printNum(IDx):
for num in range(IDx ):
#打印当前运行的线程名字
print("{0}tnum={1}".format(threading.current_thread().getname(), num) )
delay = math.ceil(random.random() * 2)
time.sleep(delay)
if __name__ == '__main__':
th1 = threading.Thread(target=printNum, args=(2,),name="thread1" )
th2 = threading.Thread(target=printNum, args=(3,),name="thread2" )
#启动2个线程
th1.start()
th2.start()
#等待至线程中止
th1.join()
th2.join()
print("{0} 线程结束".format(threading.current_thread().getname()))
运行脚本得到以下结果。
thread1 num=0
thread2 num=0
thread1 num=1
thread2 num=1
thread2 num=2
MainThread 线程结束
运行脚本默认会启动一个线程,把该线程称为主线程,主线程有可以启动新的线程,Python的threading模块有个current_thread()函数,它将返回当前线程的示例。从当前线程的示例可以获得前运行线程名字,核心代码如下。
threading.current_thread().getname()
启动一个线程就是把一个函数和参数传入并创建Thread实例,然后调用start()开始执行
th1 = threading.Thread(target=printNum, args=(2,),name="thread1" )
th1.start()
从返回结果可以看出主线程示例的名字叫MainThread,子线程的名字在创建时指定,本例创建了2个子线程,名字叫thread1和thread2。如果没有给线程起名字,Python就自动给线程命名为Thread-1,Thread-2…等等。在本例中定义了线程函数printNum(),打印IDx次记录后退出,每次打印使用time.sleep()让程序休眠一段时间。
第二种创建线程方式:创建线程类
直接创建threading.Thread的子类来创建一个线程对象,实现多线程。通过继承Thread类,并重写Thread类的run()方法,在run()方法中定义具体要执行的任务。在Thread类中,提供了一个start()方法用于启动新进程,线程启动后会自动调用run()方法。
import threading
import time,random,math
class MutliThread(threading.Thread):
def __init__(self, threadname,num):
threading.Thread.__init__(self)
self.name = threadname
self.num = num
def run(self):
for i in range(self.num):
print("{0} i={1}".format(threading.current_thread().getname(), i))
delay = math.ceil(random.random() * 2)
time.sleep(delay)
if __name__ == '__main__':
thr1 = MutliThread("thread1",3)
thr2 = MutliThread("thread2",2)
# 启动线程
thr1.start()
thr2.start()
# 等待至线程中止
thr1.join()
thr2.join()
print("{0} 线程结束".format(threading.current_thread().getname()))
运行脚本得到以下结果。
thread1 i=0
thread2 i=0
thread1 i=1
thread2 i=1
thread1 i=2
MainThread 线程结束
从返回结果可以看出,通过创建Thread类来产生2个线程对象thr1和thr2,重写Thread类的run()函数,把业务逻辑放入其中,通过调用线程对象的start()方法启动线程。通过调用线程对象的join()函数,等待该线程完成,在继续下面的 *** 作。
在本例中,主线程MainThread等待子线程thread1和thread2线程运行结束后才输出” MainThread 线程结束”。如果子线程thread1和thread2不调用join()函数,那么主线程MainThread和2个子线程是并行执行任务的,2个子线程加上join()函数后,程序就变成顺序执行了。所以子线程用到join()的时候,通常都是主线程等到其他多个子线程执行完毕后再继续执行,其他的多个子线程并不需要互相等待。
守护线程
在线程模块中,使用子线程对象用到join()函数,主线程需要依赖子线程执行完毕后才继续执行代码。如果子线程不使用join()函数,主线程和子线程是并行运行的,没有依赖关系,主线程执行了,子线程也在执行。
在多线程开发中,如果子线程设定为了守护线程,守护线程会等待主线程运行完毕后被销毁。一个主线程可以设置多个守护线程,守护线程运行的前提是,主线程必须存在,如果主线程不存在了,守护线程会被销毁。
在本例中创建1个主线程3个子线程,让主线程和子线程并行执行。内容如下。
import threading, time
def run(taskname):
print("任务:", taskname)
time.sleep(2)
print("{0} 任务执行完毕".format(taskname)) # 查看每个子线程
if __name__ == '__main__':
start_time = time.time()
for i in range(3):
thr = threading.Thread(target=run, args=("task-{0}".format(i),))
# 把子线程设置为守护线程
thr.setDaemon(True)
thr.start()
# 查看主线程和当前活动的所有线程数
print("{0}线程结束,当线程数量={1}".format( threading.current_thread().getname(), threading.active_count()))
print("消耗时间:", time.time() - start_time)
。
运行脚本得到以下结果:
任务: task-0
任务: task-1
任务: task-2
MainThread线程结束,当线程数量=4
消耗时间: 0.0009751319885253906
task-2 任务执行完毕
task-0 任务执行完毕
task-1 任务执行完毕
从返回结果可以看出,当前的线程个数是4,线程个数=主线程数 + 子线程数,在本例中有1个主线程和3个子线程。主线程执行完毕后,等待子线程执行完毕,程序才会退出。
在本例的基础上,把所有的子线程都设置为守护线程。子线程变成守护线程后,只要主线程执行完毕,程序不管子线程有没有执行完毕,程序都会退出。使用线程对象的setDaemon(True)函数来设置守护线程。
import threading, time
def run(taskname):
print("任务:", taskname)
time.sleep(2)
print("{0} 任务执行完毕".format(taskname))
if __name__ == '__main__':
start_time = time.time()
for i in range(3):
thr = threading.Thread(target=run, args=("task-{0}".format(i),))
# 把子线程设置为守护线程,在启动线程前设置
thr.setDaemon(True)
thr.start()
# 查看主线程和当前活动的所有线程数
thrname = threading.current_thread().getname()
thrCount = threading.active_count()
print("{0}线程结束,当线程数量={1}".format(thrname, thrCount))
print("消耗时间:", time.time() - start_time)
运行脚本得到以下结果。
任务: task-0
任务: task-1
任务: task-2
MainThr
原文链接:https://blog.csdn.net/BF02jgtRS00XKtCx/article/details/91074238
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。 发表于 2021-06-14 16:36 阅读 ( 101 ) 分类:Linux 总结
以上是内存溢出为你收集整理的Python线程5分钟完全解读全部内容,希望文章能够帮你解决Python线程5分钟完全解读所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)