时间:2021-05-22
前言
个人一直觉得对学习任何知识而言,概念是相当重要的。掌握了概念和原理,细节可以留给实践去推敲。掌握的关键在于理解,通过具体的实例和实际操作来感性的体会概念和原理可以起到很好的效果。本文通过一些具体的例子简单介绍一下python的多线程和多进程,后续会写一些进程通信和线程通信的一些文章。
python多线程
python中提供两个标准库thread和threading用于对线程的支持,python3中已放弃对前者的支持,后者是一种更高层次封装的线程库,接下来均以后者为例。
创建线程
python中有两种方式实现线程:
1.实例化一个threading.Thread的对象,并传入一个初始化函数对象(initial function )作为线程执行的入口;
2.继承threading.Thread,并重写run函数;
方式1:创建threading.Thread对象
结果:
This is main functionThis is thread 2 running....This is thread 1 running....方式2:继承threading.Thread,并重写run
执行结果同方式1.
threading.Thread
上面两种方法本质上都是直接或者间接使用threading.Thread类
threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
关联上面两种创建线程的方式:
import threadingimport timeclass CustomThread(threading.Thread): def __init__(self, thread_name, target = None): # step 1: call base __init__ function super(CustomThread, self).__init__(name=thread_name, target=target, args = (thread_name,)) self._tname = thread_name def run(self): # step 2: overide run function # time.sleep(0.5) # print("This is %s running....@run" % self._tname) super(CustomThread, self).run()def target(arg): time.sleep(0.5) print("This is %s running....@target" % arg)if __name__ == "__main__": t1 = CustomThread("thread 1", target) t2 = CustomThread("thread 2", target) t1.start() t2.start() print("This is main function")结果:
This is main functionThis is thread 1 running....@targetThis is thread 2 running....@target上面这段代码说明:
1.两种方式创建线程,指定的参数最终都会传给threading.Thread类;
2.传给线程的目标函数是在基类Thread的run函数体中被调用的,如果run没有被重写的话。
threading模块的一些属性和方法可以参照官网,这里重点介绍一下threading.Thread对象的方法
下面是threading.Thread提供的线程对象方法和属性:
这些是我们创建线程之后通过线程对象对线程进行管理和获取线程信息的方法。
多线程执行
在主线程中创建若线程之后,他们之间没有任何协作和同步,除主线程之外每个线程都是从run开始被执行,直到执行完毕。
join
我们可以通过join方法让主线程阻塞,等待其创建的线程执行完成。
import threadingimport timedef tstart(arg): print("%s running....at: %s" % (arg,time.time())) time.sleep(1) print("%s is finished! at: %s" % (arg,time.time()))if __name__ == '__main__': t1 = threading.Thread(target=tstart, args=('This is thread 1',)) t1.start() t1.join() # 当前线程阻塞,等待t1线程执行完成 print("This is main function at:%s" % time.time())结果:
This is thread 1 running....at: 1564906617.43This is thread 1 is finished! at: 1564906618.43This is main function at:1564906618.43如果不加任何限制,当主线程执行完毕之后,当前程序并不会结束,必须等到所有线程都结束之后才能结束当前进程。
将上面程序中的t1.join()去掉,执行结果如下:
This is thread 1 running....at: 1564906769.52This is main function at:1564906769.52This is thread 1 is finished! at: 1564906770.52可以通过将创建的线程指定为守护线程(daemon),这样主线程执行完毕之后会立即结束未执行完的线程,然后结束程序。
deamon守护线程
import threadingimport timedef tstart(arg): print("%s running....at: %s" % (arg,time.time())) time.sleep(1) print("%s is finished! at: %s" % (arg,time.time()))if __name__ == '__main__': t1 = threading.Thread(target=tstart, args=('This is thread 1',)) t1.setDaemon(True) t1.start() # t1.join() # 当前线程阻塞,等待t1线程执行完成 print("This is main function at:%s" % time.time())结果:
This is thread 1 running....at: 1564906847.85This is main function at:1564906847.85python多进程
相比较于threading模块用于创建python多线程,python提供multiprocessing用于创建多进程。先看一下创建进程的两种方式。
The multiprocessing package mostly replicates the API of the threading module. —— python doc
创建进程
创建进程的方式和创建线程的方式类似:
1.实例化一个multiprocessing.Process的对象,并传入一个初始化函数对象(initial function )作为新建进程执行入口;
2.继承multiprocessing.Process,并重写run函数;
方式1:
结果:
Process name: subprocess, pid: 4888 subprocess pid: 4888current process pid: 9912方式2:
这里可以思考一下,如果像多线程一样,存在一个全局的变量share_data,不同进程同时访问share_data会有问题吗?
由于每一个进程拥有独立的内存地址空间且互相隔离,因此不同进程看到的share_data是不同的、分别位于不同的地址空间,同时访问不会有问题。这里需要注意一下。
Subprocess模块
既然说道了多进程,那就顺便提一下另一种创建进程的方式。
python提供了Sunprocess模块可以在程序执行过程中,调用外部的程序。
如我们可以在python程序中打开记事本,打开cmd,或者在某个时间点关机:
>>> import subprocess>>> subprocess.Popen(['cmd'])<subprocess.Popen object at 0x0339F550>>>> subprocess.Popen(['notepad'])<subprocess.Popen object at 0x03262B70>>>> subprocess.Popen(['shutdown', '-p'])或者使用ping测试一下网络连通性:
>>> res = subprocess.Popen(['ping', 'munication)进行数据传输;线程和进程的上下文切换
进程切换过程切换牵涉到非常多的东西,寄存器内容保存到任务状态段TSS,切换页表,堆栈等。简单来说可以分为下面两步:
页全局目录切换,使CPU到新进程的线性地址空间寻址;
切换内核态堆栈和硬件上下文,硬件上下文包含CPU寄存器的内容,存放在TSS中;
线程运行于进程地址空间,切换过程不涉及到空间的变换,只牵涉到第二步;
使用多线程还是多进程?
CPU密集型:程序需要占用CPU进行大量的运算和数据处理;
I/O密集型:程序中需要频繁的进行I/O操作;例如网络中socket数据传输和读取等;
由于python多线程并不是并行执行,因此较适合与I/O密集型程序,多进程并行执行适用于CPU密集型程序;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
python多线程和多进程区别是: 1、多线程可以共享全局变量,而多进程是不能的。 2、多线程中,所有子线程的进程号相同;多进程中不同的子进程进程号不同。
linux下的C\C++多进程多线程编程实例详解1、多进程编程#include#include#includeintmain(){pid_tchild_pid;
Python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包
python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU资源,在python中大部分情况需要使用多进程。python提供了非常好用的多进程包M
python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包