进程&&线程
进程和线程
进程
定义:进程就是一个程序在一个数据集上的一次动态执行过程
进程一般由
程序、数据集、进程控制块
三部分组成。
数据集:
则是程序在执行过程中所需要使用的资源;
进程控制块:
用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志。
线程
线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干一样事的缺陷,使到进程内并发成为可能。
区别和关系:
1.一个程序至少有一个进程,一个进程至少有一个线程.(进程可以理解成线程的容器)
线程:
是最小的执行单元,不能独立执行,共享所属进程的资源
一个线程可以创建和撤销另一个线程,同一进程中线程可并发
进程:是最小的资源分配单元,不能资源共享,有独立的资源空间
python的GIL
GIL:python中,在同一时刻只能有一个线程进入解释器
threading的两种调度方法
直接调用:
1 import threading 2 import time 3 def Hed(num): 4 print(num) 5 time.sleep(3) 6 if __name__ =="__main__": 7 t1 = threading.Thread(target=Hed,args=(10,)) 8 t1.start() 9 t2 = threading.Thread(target=Hed,args=(20,)) 10 t2.start() 11 print("ending")
继承调用:
1 class MyThread(threading.Thread): 2 def __init__(self, num): 3 4 5 threading.Thread.__init__(self) 6 self.num = num 7 8 def run(self): # 定义每个线程要运行的函数 9 print("running on number:%s" % self.num) 10 time.sleep(3) 11 if __name__=='__main__': 12 t1 = MyThread(1) 13 t2 = MyThread(2) 14 t1.start() 15 t2.start()
join和setDaemon
join():在子线程完成运行之前,这个子线程的父线程将一直被阻塞。
setDaemon(True):
将线程声明为守护线程,必须在start() 方法调用之前设置, 如果不设置为守护线程程序会被无限挂起。这个方法基本和join是相反的。
正常情况下:当我们在程序运行中,执行一个主线程,如果主线程又创建一个子线程,主线程和子线程 就分兵两路,分别运行,那么当主线程完成
想退出时,会检验子线程是否完成。如果子线程未完成,则主线程会等待子线程完成后再退出。但是有时候我们需要的是只要主线程
完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以 用setDaemon方法
一般情况下:
1 import threading 2 import time 3 def Music(): 4 5 print("Listen music...........%s"%time.ctime()) 6 time.sleep(3) 7 print("Stop music..............%s"%time.ctime()) 8 9 def Videos(): 10 11 print("See videos ............%s"%time.ctime()) 12 time.sleep(5) 13 print("Stop videos............%s"%time.ctime()) 14 15 16 t1 = threading.Thread(target=Music) 17 t2 = threading.Thread(target=Videos) 18 19 if __name__ == '__main__': 20 21 t1.start() 22 t2.start() 23 print('end ..................%s'%time.ctime())
结果:
如果: t1 = threading.Thread(target=Music())
t2 = threading.Thread(target=Videos())
结果:会和一般的进程执行相同没有并发
加t1.join()后结果:
加t2.join()后结果:
加t1.setDaemon(True)后结果:
原因:主进程在等待videos这个进程执行完了才是真的结束了,输出end….并不是真的主进程结束,
t1是守护进程那么t2才是主进程结束的标志
加t2.setDaemon(True)后结果:
原因:t2是守护进程了,所以主进程结束的标志看t1,t1一结束标志主进程结束了,那么后面的守护进程就不再执行了
其他方法:
# run(): 线程被cpu调度后自动执行线程对象的run方法 # start():启动线程活动。 # isAlive(): 返回线程是否活动的。 # getName(): 返回线程名。 # setName(): 设置线程名。 threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程变量。 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。