线程及其开启方式和方法


初识线程

在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程,cpu真正的执行单位是线程

这和在工厂中很像,在工厂中,每个车间都有房子,而且每个车间默认有一条流水线

所以,我们可以吧操作系统和工厂进行类比:

操作系统 ===> 工厂 进程 ===> 车间 线程 ===> 流水线 cpu ===> 电源 线程:cpu最小的执行单位 进程:资源集合/资源单位. 线程运行 = 运行代码 进程运行 = 各种资源 + 线程

右键运行:
申请内存空间,先把解释器丢进去并且把代码丢进去(进程做的),运行代码(线程).

进程和线程的区别:

过程描述的区别

线程==》单指代码的执行过程 进程==》资源的申请与销毁的过程

进程内存空间彼此隔离
同一个进程下的线程共享资源.

进程和线程的创建速度
进程需要申请资源开辟空间 慢
只是告诉操作系统一个执行方案 快

线程开启的俩种方式

线程开启的方式和进程十分的类似,我就不进行详细说明了,他也是分为方法和类俩种

线程用的是throading模块

方式一

fr threading import Thread import time def task(): print('线程 start') time.sleep(2) print('线程 end') if __name__ == '__main__': t = Thread(target=task) t.start() # 告诉操作系统开一个线程 . print('主')

方式二

fr threading import Thread import time # 进程等待所有线程结束才会结束 class Myt(Thread): def run(self): print('子线程 start') time.sleep(5) print('子线程 end') t = Myt() t.start() print('主线程')

线程和进程创建速度比较

进程在创建时,开启子进程需要申请资源开辟空间,较慢

而线程在开启子线程只是告诉操作系统一个执行方案,较快

我们可以用代码进行比较

fr threading import Thread fr multiprocessing import Process import time def task(name): print(f' is running') time.sleep(2) print(f' is end') if __name__ == '__main__': t = Thread(target=task,args=('子线程',)) p = Process(target=task,args=('子进程',)) # t.start() p.start() print('主') 开启子线程的打印效果: 子线程 is running 主 子线程 is end ================== 开启子进程打印效果: 主 子进程 is running 子进程 is end ================== 俩者都开启的打印效果: 子线程 is running 主 子进程 is running 子线程 is end 子进程 is end

子线程共享资源

fr threading import Thread import time, os x = 100 def task(): global x x = 50 print(os.getpid()) # 12024 if __name__ == '__main__': t = Thread(target=task) t.start() time.sleep(2) print(x) # 50 print(os.getpid()) # 12024

x的值被改变了,说明用的是同一个资源,也就是说,同一进程下的线程共享同一资源

线程的join方法

线程的join的使用方法大体上和进程还是有些类似的,话不多说,直接上代码吧

fr threading import Thread import time def task(): print('子线程 start') time.sleep(2) print('子线程 end') t = Thread(target=task) t.start() t.join() # 等待子线程运行结束 print('主线程')

主线程会在子线程运行完之后再执行

多线程的join

当三个线程运行时间分别为1,2,3秒,执行时间会是多少呢?

fr threading import Thread import time def task(name,n): print(f' start') time.sleep(n) print(f' 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() # 111s t2.join() # t3.join() end = time.time() # 3.00322350921 # 思考一下 在单核的情况下 多个线程是如何利用cpu的 print(endstart) # print('主线程')

在单核的情况下,cpu先执行t1的start,遇到io之后直接跳到t2,在t2遇到io后又会跳到t3,等t1sleep完之后再执行t1的end,依次推类

将这里和之前进程相比较,也可以发现线程的速度比进程快的多得多

了解进程的join

fr multiprocessing import Process fr threading import Thread import time def task(): print('进程 开启') time.sleep(10) print('进程 结束') def task2(): print('子线程 开启') time.sleep(2) print('子线程 结束') if __name__ == '__main__': p = Process(target=task) t = Thread(target=task2) t.start() # 开线程 p.start() # 开进程 print('子进程join开始') p.join() # 主进程的主线程等待子进程运行结束 print('主')

结果为:

子线程 开启 子进程join开始 进程 开启 子线程 结束 进程 结束 主

可以发现,以往都说p.join是主进程等待子进程运行结束,现在我们发现,主进程的子线程并没有等待子进程运行结束,只有主进程的主线程才等待子进程运行结束

线程的其他相关用法

线程除了最常用的join,还有其他用法,其中大部分都和进程差不多,这里就不一一赘述,直接用代码来展示吧

fr threading import Thread,currentThread,enumerate,activeCount # import threading import time # threadingurrent_thread() # threadingurrent_thread() def task(): print('子线程 start') time.sleep(2) print('子线程 end') print(enumerate()) # print(currentThread(),'子线程') if __name__ == '__main__': t1 = Thread(target=task) t2 = Thread(target=task) t1.start() t2.start() # print(t1.is_alive()) # True # print(t1.getName()) # Thread1 # print(t2.getName()) # Thread2 # t1.setName('班长') # print(t1.getName()) # print(currentThread().name) # print(enumerate()) # [<_MainThread(MainThread, started 1856)>, <Thread(Thread1, started 6948)>, <Thread(Thread2, started 3128)>] # print(activeCount()) # 3 # print(len(enumerate())) # 3

在这里,我们已经写了一个fr threading import Thread之后,还可以写import threading,这样并不会占用更多的空间,当你需要别的东西的时候可以直接threading.xx就可以了

守护线程

守护的是进程的运行周期

def task(): print('守护线程开始') print(currentThread()) time.sleep(20) # print('守护线程结束') 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('主')

线程的守护线程会在进程结束的时候结束,也就是task中的print(currentThread())会在print('主')之后打印出来。但是task线程在sleep的时候主线程结束了,所以 最后的守护线程结束不会被打印



上一篇:Win11内核隔离无法启动,彻底删除AliPaladin64

下一篇:Microsoft Edge浏览器收藏夹网页(书签)怎么默认新建标签页打开


Copyright © 2002-2019 k262电脑网 www.k262.cn 皖ICP备2020016292号
温馨提示:部分文章图片数据来源与网络,仅供参考!版权归原作者所有,如有侵权请联系删除!QQ:251442993 热门搜索 网站地图