手把手教你做项目多线程篇——基础知识详解

网友投稿 616 2022-05-30

项目中多线程的目的

具体原理我觉得这应该是可以跳到操作系统里面了一点点小小总结大家还可以找本操作系统的书看看,老规矩找不到的话找我主页,有一个关于资源的文章里面有资源当然也可以私信我。

我们再说说我们项目里面用多线程的目的:

1.线程之间共享内存非常容易。

2·使用多线程来实现多任务并发执行比使用多进程的效率高

3·有时候可以节省运行时间,这个一会在下面就会知道

4·当你一个文件要同时执行多个功能时就可以用到多线程

python语言内置了多线程功能支持,而不是单纯地作为底层操作系统的调度方式,从而简化了python的多线程编程

实战操作

说这么多不如实际动手练练,首先导入线程

特别注意:

大家在见建文件的时候名字千万别和导入的包threading一样不然会出错的。

小知识

import threading

让我们先看看自己程序现在有多少个进程

import threading def main(): print(threading.current_thread()) if __name__ == '__main__': main()

结果:1#我的就一个你的呢?

如果你的进程不为一的话还可以这样查看每一个进程名

import threading def main(): print(threading.active_count()) print(threading.enumerate()) if __name__ == '__main__': main()

>>>[<_MainThread(MainThread, started 36004)>]#返回的是一个列表因为我的目前就一个所以就一个主进程

还可以查看正在运行的进程

import threading def main(): print(threading.active_count()) print(threading.enumerate()) print(threading.current_thread()) if __name__ == '__main__': main()

>1 [<_MainThread(MainThread, started 36004)>] <_MainThread(MainThread, started 36004)>

创建一个简单的线程

首先我们先介绍一下threading.Thread()里面的参数,大家学python每个模块的功能时最好还是看一下源文件内容,这样有助于提高你的编程能力:

需要注意的点我已经打上标记了

import threading def first(): print("frist active") print("frist finish") def main(): first_thread=threading.Thread(target=first,name="T1") first_thread.start()#开始的标志 print("main") if __name__ == '__main__': main()

结果: 第一次运行 frist active main frist finish 第二次运行 frist active frist finish main

每次的结果不一样就已经表明Frist和main是同时运行的了。

如果说效果不太明显的话,我们改进一下接下来我们引入

import time

import threading import time def first(): print("frist active") time.sleep(3) print("frist finish") def main(): first_thread=threading.Thread(target=first,name="T1") first_thread.start() print("main") if __name__ == '__main__': main()

结果: frist active main frist finish

因为执行到Frist active的时候Frist线程要睡3秒这个时候main还在执行所以这样每次都是这个结果了。

特别强调target=first不是导入Frist函数从源文件我们就已经看出是通过run()方法进行的,这里解释我引用一位大佬解释

当然如果你觉得这样不行的话你也可以重写threading.Thresd里的run方法来个自定义线程

class MyThread(threading.Thread): def __init__(self,n): super(MyThread,self).__init__() #重构run函数必须写 self.n = n def run(self): print('task',self.n) time.sleep(1) print('2s') time.sleep(1) print('1s') time.sleep(1) print('0s') time.sleep(1) if __name__ == '__main__': t1 = MyThread('t1') t2 = MyThread('t2') t1.start() t2.start()

结果: task t1 task t2 2s 2s 1s 1s 0s 0s

守护线程

所谓’线程守护’,就是主线程不管该线程的执行情况,只要是其他子线程结束且主线程执行完毕,主线程都会关闭。也就是说:主线程不等待该守护线程的执行完再去关闭。

不好理解的话来看看例子

import threading import time def first(): print("frist active") time.sleep(3) print("frist finish") def second(): print("second active") print("second finish") def main(): first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.setDaemon(True)#一定要在start()前开始 first_thread.start() second_thresd.start() print("main") if __name__ == '__main__': main()

结果 frist active second active second finishjiemeijieshu main

当主线程和其他子线程都结束不管守护线程first_thread 结没结束程序都结束

当设second_thresd为守护线程的时候情况是这样的

import threading import time def first(): print("frist active") time.sleep(3) print("frist finish") def second(): print("second active") print("second finish") def main(): first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") second_thresd.setDaemon(True)#一定要在start()前开始 first_thread.start() second_thresd.start() print("main") if __name__ == '__main__': main()

frist active second active second finish main frist finish #尽管输出这个要等三秒

主进程等待子进程结束

为了让守护线程执行结束之后,主线程再结束,我们可以使用join方法,让主线程等待子线程执行

import threading import time def first(): print("frist active") time.sleep(3) print("frist finish") def second(): print("second active") print("second finish") def main(): first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.start() second_thresd.start() first_thread.join() print("main") if __name__ == '__main__': main()

结果: frist active second active second finish frist finish main 不加join是这样的结果 frist active second active second finish main frist finish

共享全局变量的特性

这里定义一个全局变量A

import threading import time def first(): global A print("frist active") time.sleep(3) A=A+3 print("frist:%d"%A) print("frist finish") def second(): global A print("second active") A=A+6 print("second:%d"%A) print("second finish") def main(): global A first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.start() second_thresd.start() #first_thread.join() print("main") A=A+3 print("mian:%d"%A) if __name__ == '__main__': A=0 main()

来看一下结果

frist active second active second:6 second finish main mian:9 frist:12 frist finish

由上面的例子可以看出,输出A的值的时候不同进程之间的资源是共享的这就导致了变量A的值不固定造成了脏数据的情况,不理解的话我们就来个例子。

在没有互斥锁的情况下,假设账户有一万元钱,存钱和取钱同时进行可能账户余额会有一万一千元。这样我当然高兴只是银行不答应。为了避免这种情况我们引入锁的概念,下面我们简单的介绍几种编程里面常用的。

互斥锁

import threading import time def first(): global A,lock lock.acquire() print("frist active") time.sleep(3) A=A+3 print("frist:%d"%A) print("frist finish") lock.release() def second(): global A,lock lock.acquire() print("second active") A=A+6 print("second:%d"%A) print("second finish") lock.release def main(): global A,lock lock=threading.Lock() first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.start() second_thresd.start() #first_thread.join() print("main") A=A+3 print("mian:%d"%A) if __name__ == '__main__': A=0 main()

结果

frist active main mian:3 frist:6 frist finish second active second:12 second finish

是不是这样看着就舒服多了,如果例子不够明显我们再来一个

import threading import time def first(): global A,lock lock.acquire() print("frist active") time.sleep(3) A=A+3 print("frist1:%d"%A) A = A + 3 print("frist2:%d" % A) print("frist finish") lock.release() def second(): global A,lock lock.acquire() print("second active") A=A+6 print("second1:%d"%A) A=A+6 print("second2:%d"%A) print("second finish") lock.release() def main(): global A,lock lock=threading.Lock() first_thread=threading.Thread(target=first,name="T1") second_thresd=threading.Thread(target=second,name="T2") first_thread.start() second_thresd.start() #first_thread.join() print("main") A=A+3 print("mian:%d"%A) if __name__ == '__main__': A=0 main()

结果

frist active main mian:3 frist1:6 frist2:9 frist finish second active second1:15 second2:21 second finish 去掉锁以后结果 frist active second active second1:6 second2:12 second finish main mian:15 frist1:18 frist2:21 frist finish

很明显去掉锁以后结果杂乱的很

信号量

我相信对操作系统有一定了解的肯定,在刚才提到锁的时候就想到了信号量毕竟考研题经常会出现,同步,互斥和信号量机制。我们就来说一说信号量锁,其实道理很简单假如你现在,在中国结婚了你只能娶一个老婆吧,尽管你可以去找别的女人但他们不能称为老婆她们会被称为小三,二奶啊等等,这里老婆这个信号量在中国就是==一==只能有一个,别的再来就不可以了。

import threading import time def run(n,semaphore): semaphore.acquire() #加锁 time.sleep(3) print('run the thread:%s\n' % n) semaphore.release() #释放 if __name__== '__main__': num=0 semaphore = threading.BoundedSemaphore(3) #最多允许3个线程同时运行 for i in range(10): t = threading.Thread(target=run,args=('t-%s' % i,semaphore)) t.start() while threading.active_count() !=1: pass else: print('----------all threads done-----------')

结果

手把手教你做项目多线程篇——基础知识详解

run the thread:t-2 run the thread:t-1 run the thread:t-0 run the thread:t-3 run the thread:t-5 run the thread:t-4 run the thread:t-6 run the thread:t-7 run the thread:t-8 run the thread:t-9 ----------all threads done-----------

任务调度 多线程

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:springmvc实战技巧解析(十六)程序员必备流程图
下一篇:区块链开发公司 区块链能体现什么作用呢?
相关文章