一、线程
-
初识线程
在传统操作系统种,每个进程有一个地址空间,而且默认就有一个控制线程,cpu真正的执行单位是线程。
在工厂中,每一个车间都有房子,而且每个车间默认就有一个流水线。 -
做一个比较
相当于
操作系统------->工厂
进程------->车间
线程------->流水线
cpu------->电源 -
线程:cpu最小的执行单位
进程:资源集合/资源单位
线程运行 ------->代码运行
进程运行------->各种资源 + 线程 -
右键运行会发生的事情:申请内存空间,先将解释器代码丢进去并且把python代码丢进去(进程做的)(内存运行的时候不识别python文件代码,只有解释器才能识别python文件代码,所有先把解释器放入内存),运行代码(线程)
-
进程和线程的区别:
过程描述的区别
线程------->单指代码的执行过程
进程------->资源的申请与销毁的过程 -
进程内存空间彼此隔离(内存共享or隔离)
多个进程内存空间彼此隔离。
同一进程下的多个线程共享该进程内的数据。同一个进程下的线程共享资源
-
进程和线程的创造速度
进程需要申请资源开辟空间------->慢
只是告诉操作系统一个执行方案------->快 -
1 进程的启动和销毁(空间开始和释放)
只要一说一个进程启动了,那你知道了一个事情,是关于这个程序的一块空间造好了。
只要一说进程销毁了,那你也知道了一个事情,是关于这个程序的空间释放了。
2 线程的启动和销毁(进程里的一段代码运行起来了,进程里的一段代码运行结束)
-
进程之间是竞争关系,线程之间是协作关系?(了解)
车间直接是竞争/抢电源的关系,竞争(不同的进程直接是竞争关系,是不同的程序员写的程序运行的,迅雷抢占其他进程的网速,360把其他进程当做病毒干死)
一个车间的不同流水线式协同工作的关系(同一个进程的线程之间是合作关系,是同一个程序写的程序内开启动,迅雷内的线程是合作关系,不会自己干自己)
二、开启线程的俩种方式
由于线程开启不会出现一直循环调用开启的情况和进程是不同的,所以不需要用main来隔绝,但可以使用。
2.1方式1
from threading import Thread
import time
def task():
print('线程 start')
time.sleep(2)
print('线程end')
if __name__ == '__main__':
t = Thread(target=task)
t.start()
print('主进程')
################
线程 start
主进程
线程end
2.2方式2
from threading import Thread
import time
class Myt(Thread):
def run(self):
print('子进程 start')
time.sleep(2)
print('子进程 end')
t = Myt()
t.start()
print('主')
#######################
子进程 start
主
子进程 end
三、子进程vs子线程创建速度
from threading import Thread
from multiprocessing import Process
import time
def task(name):
print(f'{name} is runing')
time.sleep(2)
print(f'{name} is endding')
if __name__ == '__main__':
t= Thread(target=task,args=('子线程',))
p = Process(target=task,args=('子进程',))
t.start()
p.start()
print('主')
##########################
子线程 is runing
主
子进程 is runing
子线程 is endding
子进程 is endding
from threading import Thread
from multiprocessing import Process
import time
def task(name):
print(f'{name} is runing')
time.sleep(2)
print(f'{name} is endding')
if __name__ == '__main__':
t= Thread(target=task,args=('子线程',))
# p = Process(target=task,args=('子进程',))
t.start()
# p.start()
print('主')
#######################
子线程 is runing
主
子线程 is endding
from threading import Thread
from multiprocessing import Process
import time
def task(name):
print(f'{name} is runing')
time.sleep(2)
print(f'{name} is endding')
if __name__ == '__main__':
# t= Thread(target=task,args=('子线程',))
p = Process(target=task,args=('子进程',))
# t.start()
p.start()
print('主')
##################
主
子进程 is runing
子进程 is endding
四、子线程共享资源
from threading import Thread
import time,os
x = 100
def task():
global x
x = 50
print(os.getpid())
if __name__ == '__main__':
t = Thread(target=task)
t.start()
time.sleep(2)
print(x)
print(os.getpid())#处于一个进程,所以pid是一样的
###########
16656
50
16656
五、线程的jion方法
5.1方法1
from threading import Thread
import time
def task():
print('子线程 start')
time.sleep(2)
print('子线程 end')
t = Thread(target=task)
t.start()
t.join()#等待子线程运行结束
print('主线程')
################
子线程 start
子线程 end
主线程
思考主线程是否会等子线程运行结束
1 其实是进程在等
貌似是主线程在原地等着,主线程已经运行完。
原来没有子线程的情况下,其实就一个主线程这一条流水线工作完了,这个进程就结束了。
那现在的情况是当前进程有其他的子线程,是进程等待自己所有的子线程运行完。
# 主进程等子进程是因为主进程要给子进程收尸
# 现在看到的等是进程必须等待其内部所有线程都运行完毕才结束。
5.2方法2
from threading import Thread
import time
def task(name,n):
print(f'{name} start')
time.sleep(n)
print(f'{name} end')
t1 = Thread(target=task,args=('线程1',1))
t2 = Thread(target=task,args=('线程2',2))
t3 = Thread(target=task,args=('线程3',3))
start = time.time()
t1.start()
t2.start()
t3.start()
t1.join()
t2.join()
t3.join()
end = time.time()
print(end-start)
##########################
线程1 start
线程2 start
线程3 start
线程1 end
线程2 end
线程3 end
3.0029337406158447
5.3了解进程的jion
from multiprocessing import Process
from threading import Thread
import time
def task():
print('进程 start')
time.sleep(10)
print('进程 end')
def task2():
print('子线程 start')
time.sleep(3)
print('子线程 end')
if __name__ == '__main__':
p = Process(target=task)
t = Thread(target=task2)
t.start()
p.start()
print('子进程的join开始')
p.join()#主进程的主线程等待子进程运行结束
print('主')
##################
子线程 start
子进程的join开始
进程 start
子线程 end
进程 end
主
六、守护线程
# 守护线程首先是一个线程。
# 守护线程守护到当前进程运行结束。
# ps:比如有未完成的子进程阶段会守护,比如有未完成的其他子线程也均会守护。
# 守护进程首先是一个进程。
# 守护进程守护到当前进程的最后一行代码结束。
from threading import Thread,enumerate,currentThread
import time
def task():
print('守护线程开始')
print(currentThread())
time.sleep(10)
print('守护线程end')
def task2():
print('子线程 start')
time.sleep(5)
print(enumerate())
print('子线程 end')
if __name__ == '__main__':
t1 = Thread(target=task)
t2 = Thread(target=task2)
t1.daemon = True
t2.start()
t1.start()
print('主')
####################
子线程 start
守护线程开始
<Thread(Thread-1, started daemon 13904)>
主
[<_MainThread(MainThread, stopped 13828)>, <Thread(Thread-2, started 3316)>, <Thread(Thread-1, started daemon 13904)>]
子线程 end
七、线程其他的相关用法
Thread实例对象的方法
- isAlive(): 返回线程是否活动的。
- getName(): 返回线程名。
- setName(): 设置线程名。
threading模块提供的一些方法:
- threading.currentThread(): 返回当前的线程变量。
- threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
- threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
-
isalive()
from threading import Thread,currentThread,enumerate,activeCount import time def task(): print('子线程 start') time.sleep(2) print('子线程 end') if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task) t1.start() t2.start() print(t1.is_alive())#子线程存在,True ################# 子线程 start 子线程 start True 子线程 end 子线程 end
-
getname()
from threading import Thread,currentThread,enumerate,activeCount import time def task(): print('子线程 start') time.sleep(2) print('子线程 end') if __name__ == '__main__': t1 = Thread(target=task) t1.start() print(t1.getName()) ########################## 子线程 start Thread-1 子线程 end
-
setname()
from threading import Thread,currentThread,enumerate,activeCount import time def task(): print('子线程 start') time.sleep(2) print('子线程 end') if __name__ == '__main__': t1 = Thread(target=task) t1.start() t1.setName('线程1') print(t1.getName()) ##################### 子线程 start 线程1 子线程 end
-
currentTread()
-
enumerate()
from threading import Thread,currentThread,enumerate,activeCount import time def task(): print('子线程 start') time.sleep(2) print('子线程 end') print(enumerate()) if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task) t1.start() t2.start() ################################### 子线程 start 子线程 start 子线程 end [<_MainThread(MainThread, stopped 12328)>, <Thread(Thread-1, started 6176)>, <Thread(Thread-2, started 14452)>] 子线程 end [<_MainThread(MainThread, stopped 12328)>, <Thread(Thread-2, started 14452)>]
from threading import Thread,currentThread,enumerate,activeCount import time def task(): print('子线程 start') time.sleep(2) print('子线程 end') if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task) t1.start() t2.start() print(enumerate()) ######################## 子线程 start 子线程 start [<_MainThread(MainThread, started 16964)>, <Thread(Thread-1, started 15796)>, <Thread(Thread-2, started 15476)>] 子线程 end 子线程 end
-
activeCount()与len(enumerate())
from threading import Thread,currentThread,enumerate,activeCount import time def task(): print('子线程 start') time.sleep(2) print('子线程 end') if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task) t1.start() t2.start() print(activeCount()) print(len(enumerate())) ################# 子线程 start 子线程 start 3 3 子线程 end 子线程 end
-
1
from threading import Thread,currentThread,enumerate,activeCount import time def task(): print('子线程 start') time.sleep(2) print('子线程 end') if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task) t1.start() t2.start() print(currentThread()) print(currentThread().name) ################## 子线程 start 子线程 start <_MainThread(MainThread, started 2696)> MainThread 子线程 end 子线程 end