python进程与线程

‘’’
Python的进程:
任务管理器,详细信息:观察列表中的PID
Linux:Terminal下运行ps -a
ps -a
ps -all
PID:是操作系统中运行的进程编号, 进程号越小,表示进程越重要

进程的概念:
    狭义上讲:特指运行起来的程序
    广义上讲:进程是一个具有特定功能的程序关于某个数据集合的一次运行活动

程序和进程的区别:
    ①. 程序是指令和数据的有序集合,程序本身不运行没有任何意义,程序是
    静态的。进程是程序在处理机制上的一次执行过程,进程是动态的。
    ②. 程序可以作为软件的资料而长期存在,进程具有生命周期。
            进程生命周期:创建、等待调用、运行、阻塞、消亡
    ③. 程序是永久的,进程是暂时的。

进程的调度机制:
    启动多个进程交替执行时,操作系统会采用一定的调度机制,
    让程序依据特定执行方式运行。
    ①. FCFS,先来先服务调度机制,依照进程创建顺序依次执行。
    适用于长期执行的进程。
    ②. SJ/PF,短作业优先执行调度机制,适用于短进程频繁执行。
    ③. 时间片轮转调度机制,让每个进程在等待队列中被分配相等的时间,
    轮转执行。

并行与并发:
    CPU的核数,N核,2N线程:
        微观串行,宏观并行,与CPU主频相关
    并行是指,资源足够时,任务同时执行。
    串行是指,资源短缺时,任务依次执行。
    并发是指,资源有限时,多任务交替执行。

进程的创建与进程的结束
    操作系统创建进程的四种方式:
    ①.系统初始化过程,如:开启系统后执行的:中断、电源管理、USB驱动等等
    ②.一个进程执行过程中,开启另外一个进程。
        关系依次为父进程与子进程(PPID,PID)
    ③.用户的交互请求时会创建进程,比如打开浏览器的图标
    ④.执行批处理的初始化过程
    
    进程的结束
    ①.进程正常的退出
    ②.进程出错退出
    ③.进程导致系统错误退出
    ④.其他任务杀死进程: ctrl + c, kill -9
    
Python进程创建:
    通过multiprocessing库中的Process模块实现进程的创建。
    ①. 进程的创建
    ②. 进程的同步
    ③. 进程池的操作
    ④. 进程之间的数据交互

Process模块的使用:
    
    from multiprocessing import Process
    Process.__init__(self, group=None, target=None, \
    name=None, args=(), kwargs={})
参数介绍:   
    使用时,需要进行关键字传参
    group:模块预留参数,不使用,值始终是None
    target:表示调用的对象,就是子进程要执行的任务
    name:子进程的名称
    args:表示调用对象的位置参数元组, args=(1,2)
    kwargs:表示低啊用对象的字典,kwargs={name='alex',value=100}

方法介绍:
    P.start(): 启动进程 ,并且调用进程中的方法 P.run()
    P.run():   进程启动时,运行的方法,通过这个方法调用target指定的函数
    P.terminate(): 强制终止进程P, 不进行清理。如果P创建了子进程,终止P
                会导致P的子进程无法操作,子进程转变为僵尸进程
    P.is_alive(): 如果P正在运行,返回布尔值True
    P.join([timeout]):主进程等待子进程运行结束

属性介绍:
    P.name: 进程名称
    P.pid:  进程号
    P.exitcode: 进程退出的返回值,正常退出时返回None
    P.authkey: 进程的身份验证键,默认是os.urandom()生成的32位字符串,
            可以为网络通信提供安全保障
    P.daemon:返回布尔值,如果是后台进程返回True,否则返回False
    
创建子进程:
    import time,os
    from multiprocessing import Process
    
    # Process.__init__(self, group=None, target=None, name=None, args=(), kwargs={})
    # def func(name):
    #     print('Hello',name)
    #     print('子进程')
    #
    # if __name__=='__main__':
    #     print('主进程开始')
    #     P = Process(target=func, args=('multiprocessing',))
    #     # start()开启进程
    #     P.start()
    #     time.sleep(1)
    #     print('主进程结束')
    
    # 运行多个子进程
    # os.getpid(),获取本进程的进程号, os.getppid(),获取本进程的父进程的进程号
    # def func():
    #     print('子进程id:',os.getpid(),'父进程id:', os.getppid())
    #
    # if __name__=='__main__':
    #     print('主进程id:',os.getpid())
    #     P_List=[]
    #     for i in range(5):
    #         P = Process(target=func)
    #         time.sleep(1)
    #         P.start()
    #         # P.join()    #串行 运行子进程后再执行主进程代码
    #         P_List.append(P)
    #     for p in P_List:
    #         p.join()    #并发机制实现,所有子进程执行结束再运行主进程代码
    #     print('主进程结束')
    
    # 通过继承Process类,自定义进程类
    # class ProcessClass(Process):
    #     # Process类本身也有__init__()方法,实例化这个类的过程中,
    #     # 也完成了与Process类实例化一样的操作过程, 同时,在这里
    #     # 传入延时时间参数用于重写run方法
    #     def __init__(self, interval):
    #         Process.__init__(self)
    #         self.interval = interval
    #     #重写run方法,调用P.start()方法过程中执行了这个方法
    #     def run(self):
    #         print('子进程ID %s 开始执行,父进程ID %s'%(os.getpid(),os.getppid()))
    #         time_start = time.time()
    #         time.sleep(self.interval)
    #         time_stop = time.time()
    #         print('子进程 %s 执行结束,耗时%.2f秒'%(os.getpid(), time_stop-time_start))
    #
    # # 主进程代码
    # def main():
    #     t_start = time.time()
    #     #创建子进程
    #     P = ProcessClass(2)
    #     P.start()
    #     P.join(0.5)
    #     t_stop = time.time()
    #     print('主进程 %s 执行结束,耗时%.2f秒' % (os.getpid(), t_stop - t_start))
    #
    # if __name__ == '__main__':
    #     main()

守护进程:
    进程分为前台进程和后台进程,守护进程是一种特殊的后台进程。
    守护进程运行不受其他进程控制。 守护进程运行时,处于原地待命状态
    有访问才执行,通常在系统休眠时才退出。
主进程 创建守护子进程:
    ①:守护进程会在主进程代码执行结束终止
    ②:守护进程内部无法开启新的子进程,否则抛出异常
    AssertionError: daemonic processes are not allowed to have children
        from multiprocessing import Process
        import os, time
        
        def task():
            print('子进程%s 开始执行'%os.getpid())
            time.sleep(2)
            print('子进程%s 执行结束'%os.getpid())
            #守护进程中 增加子进程会抛出异常
            # P = Process(target=time.sleep, args=(3,))
            # P.start()
        
        def main():
            print('主进程执行开始')
            P = Process(target=task)
            P.daemon = True
            P.start()
            P.join()# join可以调用后台的守护进程
            print('主进程执行结束')
        
        if __name__ == '__main__':
            main()
守护子进程与非守护子进程并存:
    from multiprocessing import Process
    import time, os
    
    def deamonFunc():
        print(123)
        time.sleep(1)
        print('end123')
    
    def Func():
        print(456)
        time.sleep(3)
        print('456end')
    
    def main():
        P1 = Process(target=deamonFunc)
        P2 = Process(target=Func)
        P1.daemon = True
        P1.start()
        P2.start()
        print('End!')
    
    if __name__ == '__main__':
        main()

# 随堂练习题:
# 创建多进程实现文件写入:mutiprocessing.txt, 
# 对比常规方式执行时间:open.txt
# http://www.baidu.com
# http://www.taobao.com
# http://www.sina.com
# http://www.jd.com
# http://www.qq.com
# http://www.douban.com
# http://www.google.com
# http://www.163.com            

‘’’

进程:
1. 进程号与父进程号
os.getpid()/os.getppid()
2. 并行、串行与并发
并行:资源足够,任务同时执行
串行:资源短缺,任务依次执行
并发:资源有限,多任务交替执行
3. mutiprocessing库,Process
Process.init()
target=进程对象
args=(,)进程对象的参数

    P.start()
    P.run()
    P.join()
    def SubFunc():
        print('Hello world!')
    def main():
        PList=[]
        for i in range(5):
            P = Process(target=SubFunc)
            PList.append(P)
            P.start()
            # P.join()      #串行 执行子进程
        # for i in PList:
        #     P.join()        #并发执行
        print('Done!')
    main()
创建进程的方法:
    1. 使用实例化Process对象,引用内部方法:start  join
    2. 继承方式实现子进程的创建
    class MyProcess(Process):
        def __init():
            pass
        def run():
            #重写run方法
            pass
任务:进行文件读写,创建多进程,与常规写入方式进行对比。
    多进程效率>单进程执行
    多进程:操作多个文件
    条件:工作量相同情况下
    影响运行结果的主要因素:磁盘文件处理能力, SSD,机械硬盘

‘’’
‘’’
新内容:
①. 进程的其他方法:P.terminate()
进程状态:正在运行状态,暂停,消亡
------------------------------------------
from multiprocessing import Process
import time

        class MyProcess(Process):
            def __init__(self,person):
                super().__init__()
                self.person = person
            def run(self):
                # 功能,输出人名,休眠2秒
                print('%s 正在睡觉'%self.person)
                time.sleep(2)
                print('%s 还在睡觉'%self.person)
        
        def mainFunc():
            # 传参,Person
            P1 = MyProcess('XXX')
            P1.start()
        
            P1.terminate() #关闭进程
            for i in range(100):
                print(P1.is_alive())  #判断进程是否存活
                time.sleep(0.01)
            # print(P1.is_alive())  # 判断进程是否存活
        
        if __name__ == '__main__':
            mainFunc()        
        ------------------------------------------
    
②. 进程的同步:mutiprocessing.Lock
    多进程执行时,进程直接没有顺序,为了方便对进行控制,
    使进程执行完全。增加代码的安全性,加入了进程同步机制
    ------------------------------------------
        from multiprocessing import Process,Lock
        import time,os
        
        def work(lock,n):
            lock.acquire() #加锁,同步
            print('%s :%s is running'%(n, os.getpid()))
            time.sleep(2)
            print('%s :%s is Done' % (n, os.getpid()))
            lock.release() #解锁,同步结束
        def main():
            lock = Lock()
            for i in range(3):
                P = Process(target=work,args=(lock,i,))
                P.start()
        
        if __name__ == '__main__':
            main()
    ------------------------------------------

③ 练习: 伪抢票程序:
    # 手动创建一个文本 db.txt,写入票数:1
    # 代码中实现以下功能:
    # 主进程中创建20个子进程
    # 子进程实现功能:
    # 1.查票,显示剩余票数
    # 2.买票,当前票数-1,显示剩余票数,以及买票成功信息
    # 3. 如果剩余票数<=0,显示买票失败
        from multiprocessing import Process,Lock
        
        def search():
            with open('./db','r') as f:
                return f.read()
        def get():
            count = int(search())
            print('剩余票数为%d'%count)
            if count>0:
                with open('./db','w') as f:
                    f.write(str(count-1))
                    print('买票成功,剩余票数%d'%(count-1))
                    return
            print('买票失败,剩余票数%d'%count)
        def task(lock):
            search()
            lock.acquire()
            get()
            lock.release()
        def mainFunc():
            lock=Lock()
            for i in range(20):
                P = Process(target=task, args=(lock,))
                P.start()
        
        if __name__ == '__main__':
            mainFunc()
            
    # Json读写
        from multiprocessing import Process,Lock
        import json, time
        def search():
            dic = json.load(open('db'))
            print('剩余票数为%s'%dic['count'])
        
        def get():
            # 加载json格式数据
            dic = json.load(open('db'))
            time.sleep(2)
            if dic['count']>0:
                dic['count']-=1
                #写入json格式内容到文件中
                json.dump(dic, open('db','w'))
                print('购票成功,剩余票数:%s' % dic['count'])
            else:
                print('购票失败,剩余票数:%s'%dic['count'])
        
        def task(lock):
            search()
            lock.acquire()
            get()
            lock.release()
        
        def mainFunc():
            lock = Lock()
            for i in range(10):
                P = Process(target=task,args=(lock,))
                P.start()
        
        if __name__ == '__main__':
            mainFunc()

④. 进程间通信:IPC (Inter Process Communication)
        代表进程直接可以进行数据传递。
    
    多进程实现的进程间通信,进程共享队列:
            from multiprocessing import Queue
    q = Queue([maxsize])
        创建指定大小的队列
    参数:maxsize是队列最大允许的项数
    
    队列方法介绍:
    get(self, block=True, timeout=None)
        q:是队列中的一个项目,如果q为空这个方法将处于阻塞状态,
        直到队列中有项目为止。
        block用于控制阻塞行为。默认为True。如果设置为Fals,将会引发
        异常Queue.empty
        timeout:超时时间,用于在阻塞模式下,没有项目可用会引发异常:
        Queue.empty
    
    get_nowait(self) 方法 与q.get(False)含义相同
    
    put(self, obj, block=True, timeout=None)
        将数据对象执行一次入队,
        block用于控制阻塞行为。默认为True。如果设置为Fals,将会引发
        异常Queue.empty
        timeout:超时时间,用于在阻塞模式下,没有项目可用会引发异常:
        Queue.empty
    
    put_nowait(self, obj):
    
    empty(self): 显示队列状态,如果队列为空,返回True,否则返回False
    
    full(self): 显示队列状态,如果队列已满,返回True,否则返回False 
    
    qsize(self): 返回队列中项目的数量,Mac系统下会出错
    
    --------------------------------------------------
    from multiprocessing import Queue

    q = Queue(3)
    q.put(1)
    q.put(2)
    q.put(3)
    try:
        q.put_nowait(4) # 队列已满,再次入队会导致报错,如果这里再次使用q.put会导致队列阻塞
    except Exception:
        print('队列已满')
    print(q.full())
    print(q.get())
    print(q.get())
    print(q.get())
    try:
        q.get_nowait() #如果继续使用get会导致队列阻塞
    except Exception:
        print('队列已空')
    print(q.empty())
    print(q.qsize())
    
    ---------------------------------------------
    #在父进程中创建子进程, 子进程发送数据给父进程
        from multiprocessing import Process, Queue
        import time
        
        def Sub(Q):
            for i in range(1000):
                Q.put([time.asctime(), 'from Sub','Hello'])
                time.sleep(0.01)
        
        def main():
            Q = Queue()
            P = Process(target=Sub,args=(Q,))
            P.start()
            for i in range(1000):
                print(Q.get())
        
        if __name__ == '__main__':
            main()
            
    # 子进程直接的数据交互
        # 批量生产数据,放入队列再批量获取数据
        from multiprocessing import *
        import time, os
        
        def inputFunc(Q):
            info = str(os.getpid())+'put'+str(time.asctime())
            Q.put(info)
        def outpuFunc(Q):
            info = Q.get()
            print(info)
        
        def mainFunc():
            Q = Queue()
            #创建生产数据的10个子进程
            for i in range(10):
                P = Process(target=inputFunc, args=(Q,))
                P.start()
            #创建获取数据的10个子进程
            for i in range(10):
                P = Process(target=outpuFunc, args=(Q,))
                P.start()
        
        if __name__ == '__main__':
            mainFunc()

‘’’
#生产者与消费者
from multiprocessing import Process, Queue
import time, os

做包子

def producer(Q):
for i in range(10):
time.sleep(1)
Q.put(‘包子,%s’%i)
print(’%s 做包子 %s’%(os.getpid(),i))
Q.put(None)

吃包子

def consumer(Q):
while True:
info = Q.get()
if info == None:
break
print(’%s 吃包子 %s’%(os.getpid(), info))

def mainFunc():
Q = Queue()
P = Process(target=producer, args=(Q,))
C = Process(target=consumer, args=(Q,))
P.start()
C.start()

if name == ‘main’:
mainFunc()

主要内容:
1. IPC通信方式扩充:
队列Queue,数据交互方式是双向的
管道Pipe
使用Pipe()可以返回两个连接对象。这两个连接对象代表着管道的两端。
Pipe提供的方法:
P.send() 发送数据,
P.recv() 接收数据。
P.close()关闭管道
管道实现代码:
# 完成主进程中定义管道,定义俩子进程,
# 子进程1,负责发送数据,子进程2,负责接收数据
from multiprocessing import Pipe,Process,Queue,Lock
import os, time
def sender(conn):
# while True:
# info = str(os.getpid())+‘send running’
# Q.put(info)
# time.sleep(0.2)
while True:
info = str(os.getpid()) + ‘send running’
conn.send(info)
print(‘sender Function running, %s’%info)
time.sleep(0.2)
def recver(conn):
# while True:
# print(Q.get())
while True:
print(‘接收到数据’,conn.recv())

        def mainFunc():
            #创建子进程,让子进程进行通信
            # Q = Queue()
            # P1 = Process(target=sender,args=(Q,))
            # P2 = Process(target=recver, args=(Q,))
            # P1.start()
            # P2.start()
            lock = Lock()
            send_conn,recv_conn = Pipe()
            P1 = Process(target=sender,args=(send_conn,))
            P2 = Process(target=recver, args=(recv_conn,))
            lock.acquire()
            P1.start()
            P2.start()
            lock.release()
        if __name__ == '__main__':
            mainFunc()
    --------------------------------------------
    进程池:
        使用进程池来控制进程的数目,用于提高事物处理效率
        Pool可以提供指定数目的进程,提供给用户调用,当有
        新的请求提交到Pool时,如果池未满,那么会创建新的
        进程来执行这条请求。 如果池中进程达到设定的最大值,
        那么该请求就会等待,直到池中有进程结束。

    进程池的创建流程:
        ①.导入进程池模块:
        from multiprocessing import Pool
        ②.定义进程池,设定池子的大小
        P = Pool(3)
        ③.设定进程调用方式:
            阻塞式调用:后一个进程会等待前一个进程执行结束才开始执行。
            P.apply()
            非阻塞式调用:不会等待前一个进程执行结束
            P.apply_async()
        ④.关闭进程池
        P.close()
        ⑤.等待进程池执行完毕
        P.join()
        
        代码:
            阻塞式同步调用:
                from multiprocessing import Pool
                import os,time
                
                def work(n):
                    print('%s is running'%os.getpid())
                    time.sleep(1)
                    return n**2
                
                def mainFunc():
                    P = Pool(6) #进程池中定义三个进程
                    countList = []
                    for  i in range(20):
                        rec = P.apply(work,args=(i,))
                        # 同步调用,本次调用后,直接运行进程1,返回rec,work的返回值。
                        # 执行过程中,采用阻塞式执行进程,进程1任务执行结束后,如果处于空闲状态
                        # 进程1的PID会保留,等待下一次调用。如果阻塞时间过长,计算机可能夺走PID号
                        # 等到进程继续执行时,PID发生改变。
                        countList.append(rec)
                    print(countList)
                if __name__ == '__main__':
                    mainFunc()                
            
            异步调用:
                from multiprocessing import Pool
                import os, time
                
                def work(n):
                    print('%s is running' % os.getpid())
                    time.sleep(1)
                    return n ** 2
                
                def mainFunc():
                    P = Pool(3) #进程池创建三个进程
                    countList = []
                    for i in range(20):
                        print(i) # for循环会提前运行print语句,进程池中任务还没有执行
                        recv = P.apply_async(work, args=(i,)) #同时,为进程池中进程增加任务,
                        # 并且获取 work函数的返回值。
                        countList.append(recv) #调用 apply_asyn方法时,返回的是 进程的内存地址结果
                    # 异步apply_async用法:如果使用异步方式提交任务,主进程需要使用join等待进程
                    # 内部任务处理完毕,然后才可以使用get方法采集结果。
                    # 否则,主进程结束,进程池可能没来得及执行,就一起结束了
                    P.close()
                    P.join()
                    for i in countList:
                        print(i.get(),end=' ') #使用get方法来获取apply_async的结果,
                        # 如果是apply没有get方法。原因是apply是同步执行的,立即返回结果,无需get
                
                if __name__ == '__main__':
                    mainFunc()
        #随堂练习:进程池实现创建多个子进程,抢票,db.txt,同步方式完成,默认票数3张,
                进程池10个进程
        
                from multiprocessing import Pool
                import time,os
                
                def SubFunc():
                    print(os.getpid())
                    with open('db','r') as f:
                        content = int(f.read())
                    if content>0:
                        with open('db','w') as f:
                            content-=1
                            f.write(str(content))
                            print('购票成功,剩余票数%d'%content)
                
                    else:
                        print('购票失败,剩余票数%d' % content)
                    time.sleep(0.5)
                    return content
                
                def MainFunc():
                    recList = []
                    P = Pool(3)
                    for i in range(20):
                        rec = P.apply_async(SubFunc)
                        recList.append(rec)
                    P.close()
                    P.join()
                    # for i in recList:
                    #     print(i.get())
                
                if __name__ == '__main__':
                    MainFunc()
        
        # 进程池方法:map(),可以将第二个参数以迭代访问的形式传到第一个函数类型的参数中
            from  multiprocessing import Pool
            
            def Sub(i):
                return i**2
            
            def mainFunc():
                P = Pool(processes=2)
                H = P.map(Sub, [1,2,3])
                print(H)
            
            if __name__ == '__main__':
                mainFunc()
2. 线程: Thread
        a. 进程是计算机分配资源的最小单位,线程是CPU调度的最小单位。
        CPU流水线。进程是一个实体,每一个进程都具备自己的内存空间,
        内存空间通常包括:
        文本区域(text region):
            文本区域存储处理器执行的文本信息以及代码
        数据区域(data region):
            存储变量和执行进程期间使用的动态分配内存
        堆栈区域(stack region):
            存储活动过程中调用的指令以及本地的变量
        
        b.进程只是把资源集中在一起(或者理解为是一种资源的集合),
            线程是CPU上真正执行的单位。
        
        c.一个进程中存在多个线程,进程中的多个线程共享进程的地址
            空间以及进程资源
    
    创建开销:
        创建进程的开销,需要向操作系统申请一块内存空间并且放置资源进去
        创建线程的开销,无需向操作系统申请空间,直接使用进程资源,效率高。
    
    创建线程的方式:
        mutiprocessing模块参照threading模块编写的,线程的创建与调用方式
        与进程相似。
        
    # 创建线程的第一种方式
            from threading import Thread
            import time,os
            
            def Sub(name):
                print('%s is running, PID %s'%(name,os.getpid()))
                time.sleep(2)
                print('%s is Stop, PID %s' %(name,os.getpid()))
            
            def mainFunc():
                print('Main thread is running, PID %s'%os.getpid())
                T = Thread(target=Sub, args=('Sub Thread',))
                T.start()
                # T.join()
                print('Main thread is Stop, PID %s' % os.getpid())
            
            if __name__ == '__main__':
                mainFunc()
    --------------------------------------------------
    #创建线程的第二种方式:继承
        from threading import Thread
        import time, os
        
        class Sub(Thread):
            def __init__(self, name, id):
                Thread.__init__(self) #继承父类构造方法
                self.name=name      #增加属性,用于重写run方法
                self.id = id
            def run(self):
                print('%s is running, PID %s' %(self.name, self.id))
                time.sleep(1)
                print('%s is Stop, PID %s' % (self.name, self.id))
        
        def mainFunc():
            print('Main thread is running, PID %s' % os.getpid())
            S  = Sub("Sub Thread",os.getpid())
            # 在run方法中写入 name,pid,实现调用S的属性start开启线程,线程中输出name和pid信息
            S.start()   #创建并且执行子线程
            # S.join()  #join等待子线程执行结束后,在运行主线程其余代码
            print('Main thread is Stop, PID %s' % os.getpid())
        if __name__ == '__main__':
            mainFunc()
    
    # 在主进程下创建多个子线程
        from multiprocessing import Process
        from threading import Thread
        import os
        
        def work(name):
            print('%s running,PID %s'%(name, os.getpid()))
        
        def mainFunc():
            #1.创建多个子进程
            P1 = Process(target=work,args=('P1',))
            P2 = Process(target=work,args=('P2',))
            P1.start()
            P2.start()
            print('main Process PID,',os.getpid())
        
            T1 = Thread(target=work,args=('T1',))
            T2 = Thread(target=work,args=('T2',))
            T1.start()
            T2.start()
            print('main Thread PID,',os.getpid())
        
        if __name__ == '__main__':
            mainFunc()  
    ------------------------------------------------
    Thread实例对象的方法:
        is_alive(): 返回线程是否存活
        isAlive = is_alive
        getName(): 返回线程名
        setName(): 设置线程名
    threading模块提供的方法:
        threading.current_thread():返回当前线程变量
        threading.enumerate():返回一个包含正在运行线程的list。
            正在运行的线程,启动后,终止前
        activeCount = active_count
        threading.active_count():
            返回正在运行线程的数量。
    -------------------------------------------
    例子:
        from threading import Thread
        import threading,os,time
        
        def work():
            time.sleep(2)
            print(threading.current_thread().getName())
        
        def mainFunc():
            # 在主进程中开启线程
            T = Thread(target=work)
            T.start()
            T.join()
            print(threading.current_thread().getName(), os.getpid())
            print(threading.current_thread()) #主线程
            print(threading.enumerate()) #连同主线程在内有多少个线程在执行
            print(threading.active_count())
            print('End!')
        
        if __name__ == '__main__':
            mainFunc()
    --------------------------------------------------
    守护线程:
        线程也存在守护线程,它会等待主线程执行结束进行销毁
        等待过程中都处于待命状态,通过一定调用方式可以运行守护线程
    代码:
        # 在下面代码中,主线程里再次创建子线程(非守护),同时运行守护线程与非守护线程
        # 观察运行结果!
        from threading import Thread
        import time
        
        def Daemon():
            time.sleep(2)
            print('Daemon is running')
        
        def SubFunc():
            time.sleep(2)
            print('SubFunc is running')
        def MainFunc():
            T = Thread(target=Daemon)
            T2 = Thread(target=SubFunc)
            # T.daemon = True  #守护线程方式一
            T.setDaemon(True) #守护线程方式二
            T.start()
            T2.start()
            # T.join()
            print('Main Thread running')
            print(T.isAlive)
        
        if __name__ == '__main__':
            MainFunc()
    结论:Daemon是守护线程,SubFunc是非守护线程,与主线程共用一块内存
        因此同时执行守护、非守护两个线程,Daemon会被执行。        

‘’’

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值