博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python多线程学习(上)
阅读量:5889 次
发布时间:2019-06-19

本文共 5674 字,大约阅读时间需要 18 分钟。

最近在学习python多线程,写一下随笔就当复习了。另外强烈推荐大家看一下《Python核心编程》这本书,这本书里面可以帮你学习python进阶。

一。基本概念:

1.线程:

线程又称为轻量级进程,线程之间可以进行信息共享,线程可以看成是主进程或‘主线程’的迷你进程。

2.进程:

进程又称为重量级进程,进程之间是独立的,进程间共享信息要通过  ‘进程间通信(IPC)’  来进行。

3.同步:

同步是指一个任务执行完成后,另一个任务接着进行,就是一个挨着一个,比如你在食堂打饭,一号窗口的菜好吃,有很多人排队,只有前一个打完饭,后一个才可以打饭。

4.异步:

异步是指多个任务同时进行,比如:食堂有很多打饭窗口,很多人可以同时进行打饭。

5. I/O:

I/O是 input/output 的缩写,代表的含义是读写。

6. I/O密集型代码(I/O bound):

I/O密集型是指程序进行读写操作要很多,计算相对较少。

7. 计算密集型代码(CPU bound):

计算密集型是指程序主要进行计算,而读写操作要少。

8. 并发和并行:

并发  CPU数量<线程数,并发是指相同时间间隔内执行任务。

并行 CPU数量>线程数,并行是指多个任务同时执行。

 

二。python和线程:

python代码的执行由python虚拟机(解释器主循环)来进行控制。

Python还有一个GIL(全局解释器锁),用来控制程序只有一个线程在执行。

GIL锁执行过程:

锁定

执行

释放

返回第一步。

python执行多线程时,其实是在相同时间间隔内对任务进行执行,每个任务执行一小段时间,然后挂起,在执行下一个,一直到最后一个,然后在从第一个开始,如此往复,直至结束。

python对于I/O密集型比计算密集型要友好。原因:python在执行I/O密集型程序时,主要进行文件读写,而计算较少,每个任务在计算的同时可以进行对其他以完成的计算读写,而计算密集型对于计算较多,一直占用CPU,导致处理效率不高,所以对于计算密集型并不友好。

三。threading模块

对于多线程有thread模块和threading模块。thread模块在执行多线程时,在不加锁的情况下,如果主线程结束,而子线程还未结束时,子线程会被强制停止,造成得不到运行结果。在进行多线程学习时推荐使用threading模块。

1.添加线程:  threading.Thread(target=函数名,args=(需要传入的参数))

Thread类还可以传入name,给线程命名。

2.判断线程是否激活状态: is_alive()

3.获取线程数量:  threading.active_count()

4.获取当前线程:threading.current_thread()

5.获得线程名字:.name

6.等待线程:。join()

等待与不等待:

等待:

1 def a_1(): 2     print('aaaaa') 3     time.sleep(3) 4     print('aaaaa') 5 def a_2(): 6     print('bbbbb') 7     time.sleep(5) 8     print('bbbbb') 9 def main():10     print('....start....')11     t1 = threading.Thread(target=a_1)12     t2 = threading.Thread(target=a_2)13     t1.start()14     t2.start()15     print('....end....')16 17 if __name__ == '__main__':18     main()19 20 21 运行结果:22 23 ....start....24 aaaaa25 bbbbb26 ....end....27 aaaaa28 bbbbb29 30 Process finished with exit code 0

从运行结果可以看出,在不添加等待时,运行结果并不是我们想要的结果。

下面是不用 .join()的等待:

def main():    print('....start....')    t1 = threading.Thread(target=a_1)    t2 = threading.Thread(target=a_2)    t1.start()    t2.start()    time.sleep(8)    print('....end....')if __name__ == '__main__':    main()运行结果:....start....aaaaabbbbbaaaaabbbbb....end....Process finished with exit code 0

通过添加time.sleep()语句使主线程等待子线程运行结束再运行下一步操作。打印内容均在...start....和...end...之间。

下面是运用  .join()进行等待。

def main():    print('....start....')    t1 = threading.Thread(target=a_1)    t2 = threading.Thread(target=a_2)    t1.start()    t2.start()    t1.join()    t2.join()    print('....end....')if __name__ == '__main__':    main()运行结果:....start....aaaaabbbbbaaaaabbbbb....end....Process finished with exit code 0

通过该结果可以看出,添加sleep()和join()效果一样,但是推荐使用.join() ,因为在运行程序的时候用sleep()等待,还得知道等待时间,比较麻烦。join()较为方便。

 

 

 

创建线程方法:

<1> 给Thread类传入函数

<2>给Thread类传入一个实例类

<3>创建一个子类,继承Thread类,然后将函数传入子类中

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

在不用多线程时:

import datetime def num_1():     print('start...1')     time.sleep(2)     print('end...1') def num_2():     print('start...2')     time.sleep(4)     print('end...2') def main():     a = datetime.datetime.now()     print('.............start...........')     num_1()     num_2()     print('..............end............')     b = datetime.datetime.now()     p = (b - a).seconds     print('运行%s秒 ' % p) if __name__ == '__main__':     main()

创建两个函数,分别打印不同内容,并在程序执行完成打印执行时间。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

对于<1>

下面是示范代码:   .join()是主线程等待子线程完成后在执行下一步操作。

1 import threading 2 import datetime 3 #传递函数(1) 4 def num(nu,se): 5     print('%s  start' % nu) 6     time.sleep(se) 7     print('%s  end' % nu) 8  9 time_list = [2,4]10 def main():11     a = datetime.datetime.now()12     print('.....start.....')13     thread_list = []14     for x in range(len(time_list)):15         t = threading.Thread(target=num,args=(x,time_list[x]))16         thread_list.append(t)17     for x in thread_list:18         x.start()19     for x in thread_list:20         x.join()21     print('.....end.....')22     b = datetime.datetime.now()23     p = (b - a).seconds24     print('运行%s秒' % p)25 if __name__ == '__main__':26     main()

 

<2>添加一个实例类。

class New_1():    def __init__(self,num,se):        self.num = num        self.se = se    def __call__(self):        return self.num(*self.se)    passdef main():    a = datetime.datetime.now()    print('...start...')    thread_list = []    for x in range(len(time_list)):        t = threading.Thread(target=New_1(num,(x+1,time_list[x])))        thread_list.append(t)    for x in thread_list:        x.start()    for x in thread_list:        x.join()    print('...end...')    b = datetime.datetime.now()    p = (b-a).seconds    print('运行%s秒' % p)    if __name__ == '__main__':    main() 运行结果:

...start...

1 start
2 start
1 end
2 end
...end...
运行4秒

 

Process finished with exit code 0

3.继承Thread类,将内容传递进子类中。

下面是代码:

#传递函数(1)def num(nu,se):    print('%s  start' % nu)    time.sleep(se)    print('%s  end' % nu)time_list = [2,4]class New_2(threading.Thread):    def __init__(self,num,se):        super().__init__()        self.num = num        self.se = se #对于下面的函数run()进行重写,可以灵活的定义函数,函数名必须是run(),否则在传入参数后运行时,不会运行多线程。    def run(self):        return self.num(*self.se)    passdef main():    a = datetime.datetime.now()    print('...start...')    thread_list = []    for x in range(len(time_list)):        t = New_2(num,(x,time_list[x]))        thread_list.append(t)    for x in thread_list:        x.start()    for x in thread_list:        x.join()    print('...end...')    b = datetime.datetime.now()    p = (b-a).seconds    print('运行%s秒' % p)if __name__ == '__main__':    main()运行结果:...start...0  start1  start0  end1  end...end...运行4秒Process finished with exit code 0

对于以上三种添加线程的方法,可以根据自己喜好自行选择,其他的做了解即可。

 

如果有不对的地方,还请各位给予指正。

感谢大家的阅读。

 

转载于:https://www.cnblogs.com/sniper-huohuohuo/p/8777374.html

你可能感兴趣的文章
Spring的属性依赖检查
查看>>
[LeetCode] Longest Substring with At Most Two Distinct Characters
查看>>
将不确定变为确定~transactionscope何时提升为分布式事务~再续(避免引起不必要的MSDTC)...
查看>>
SSM框架——使用MyBatis Generator自动创建代码
查看>>
Winform开发框架之框架演化
查看>>
1305 Pairwise Sum and Divide
查看>>
nginx源码学习资源(不断更新)
查看>>
二:apache的Qpid消息中间件介绍
查看>>
2.14. Spring boot with Oracle
查看>>
做一天和尚撞一天钟
查看>>
[Everyday Mathematics]20150129
查看>>
JSP连接mysql数据库的重点
查看>>
关于Go,你可能不注意的7件事(转的)
查看>>
py-faster-rcnn在windows下安装
查看>>
Python编程-基础知识-条件判断
查看>>
谈谈最近的工作
查看>>
YAML 在Python中的配置应用
查看>>
iOS - Swift Swift 语言新特性
查看>>
SAP S/4HANA 1610新版本有哪些新功能?
查看>>
微信公众平台无高级接口账号获取用户基本信息
查看>>