12、多线程:Threading、守护线程

线程与进程:

线程对于进程来说,就好似工厂里的工人,分配资源是分配到工厂,工人再去处理。 线程是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。 在单个程序中同时运行多个线程完成不同的工作,称为多线程 对于IO密集型的程序来说,多线程可以利用读IO的时间去做其他事【 IO并不占用CPU,这就好像A买个一份外卖,他只需要等着送过来然后敲A家的门就行了】; 而对于CPU密集型的程序来说,多线程的效率就不是很高了【 CPU由于要计算,切换之间要恢复之前的现场消耗相对较大,比如我同时做几份作业,一份作业做十分钟,假如十分钟做不完一份作业,那么我后面再回头做的时候,我就要好好想想刚才做到哪,刚才想到哪】

 

补充:IO需要CPU吗?知乎:https://www.zhihu.com/question/27734728

image


线程Threading:

python中多线程需要使用threading模块

线程的创建与运行:

1.直接调用threading的Thread类:

线程的创建:线程对象=thread.Thread(target=函数名,args=(参数))【补充,由于args是一个元组,单个参数时要加“,”】

线程的启动:线程对象.start(),调用start(),那么线程对象会自动去调用thread.Thread中的run()

让主线程等待其余线程结束:线程对象.join(),加了join之后,相当于阻塞了主线程,主线程只有当join的线程结束后才会向下执行

import threading,time

def run(n):
    time.sleep(1)
    print("task ",n)

t1=threading.Thread(target=run,args=("t1",))
t2 = threading.Thread(target=run,args=("t2",))

start_time=time.time()#开始时间
t1.start()
t2.start()
##因为是独立线程,如果想要主线程等待其他线程运行完毕,需要使用join
t1.join()
t2.join()
spend_time=time.time()-start_time
print(spend_time)##1.0多,说明是并行的结果

附加说明--join是阻塞等待:

import threading,time

class MyTread(threading.Thread):
    def __init__(self,name):
        super(MyTread,self).__init__()#调用父类的__init__()
        self.name=name
    def run(self):#重写方法,按自己的要求去写
        time.sleep(1)
        print("run in task",self.name,threading.current_thread(),threading.active_count())

t1=MyTread("t1")
t2=MyTread("t2")
start_time=time.time()
t1.start()
t2.start()

t1.join()
t2.join()
time.sleep(1)###主线程等待其余线程结束
print(time.time()-start_time)
#结果是2.0多,证明是join是相当于阻塞了主线程的执行,只有当线程结束后才会向下执行

 

2.继承threading的Thread类:

继承threading的Thread类的类要主要做两件事:

1.如果不做自定义变量的初始化,那么可以直接使用继承的父类的__init__(),如果需要做自定义变量的初始化,则需要先调用父类的__init__()【否则需要自己填写线程初始化相关的参数】

2.重写run,虽然继承了父类的run,但实际上如果不重写,那么我们继承threading的Thread类又有什么意义呢?为什么不直接调用threading的Thread类

import threading,time

class MyTread(threading.Thread):
    def __init__(self,name):
        super(MyTread,self).__init__()#调用父类的__init__()
        self.name=name
    def run(self):#重写方法,按自己的要求去写
        time.sleep(1)
        print("run in task",self.name,threading.current_thread(),threading.active_count())

t1=MyTread("t1")
t2=MyTread("t2")
start_time=time.time()
t1.start()
t2.start()
###主线程等待其余线程结束
t1.join()
t2.join()
print(time.time()-start_time)#结果是1.0多,证明是并行的


子线程:

  • 由一个线程启动的线程可以成为它的子线程,A启动B,B是A的子线程,A是B的父线程

 


线程的几个常用函数:

  • threading.current_thread():
返回当前正在运行的线程对象
 
  • threading.active_count():
返回当前进程中的存活的线程对象数

image

 

  • 线程对象.isAlive()方法判断线程是否存活

image

  • getName(): 返回线程名。
  • setName(): 设置线程名。

image

get_ident():获取当前线程ID。

 

 


守护线程:

  • 守护线程是起到辅助功能的,就好像魔法师放禁咒总要骑士保护一样【魔法师只需要关系自己的任务,保护他的任务交给守护者】
  • 而守护线程与主线程的关系呢,就好像备胎跟女神,去买东西的话,备胎要一直在外面等女神【守护线程运行结束就狗带,但不影响主进程结束,由主线程决定运行时间】,女神不需要等待备胎【主线程结束,守护线程也要结束,不管自身任务是否完成】
  • 与join的区别:join是阻塞等待,守护线程是并行的等待
  • 设置守护线程:线程对象.setDaemon(True)【注意!!!!!设置守护线程必须要在start()前面,不然会报错】

 

下面的代码显示了主线程并不会等待其守护线程结束:

import threading,time

class MyTread(threading.Thread):

    def __init__(self,name):
        super(MyTread,self).__init__()
        self.name=name
    def run(self):
        print("守护线程已经启动",self.name)
        time.sleep(1)
        print("run in task",self.name,threading.current_thread(),threading.active_count())

t1=MyTread("t1")
t1.setDaemon(True)
t2=MyTread("t2")
t2.setDaemon(True)
start_time=time.time()#开始时间
t1.start()
t2.start()

spend_time=time.time()-start_time
print(spend_time)##0.0多,而且三个线程都执行完毕了,说明这个是并行的等待

image

 

让主线程sleep一下,显示一下如果主线程要等待守护线程,那么是并行的等待:

 

import threading,time

class MyTread(threading.Thread):

    def __init__(self,name):
        super(MyTread,self).__init__()
        self.name=name
    def run(self):
        print("守护线程已经启动",self.name)
        time.sleep(1)
        print("run in task",self.name,threading.current_thread(),threading.active_count())

t1=MyTread("t1")
t1.setDaemon(True)
t2=MyTread("t2")
t2.setDaemon(True)
start_time=time.time()#开始时间
t1.start()
t2.start()
time.sleep(2)
spend_time=time.time()-start_time
print(spend_time)##2.0多,而且三个线程都执行完毕了,说明这个是并行的等待

image

 


转载于:https://www.cnblogs.com/progor/p/8431910.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值