目录
前言:
1进程:
1.1定义:
1.1.1进程是操作系统分配资源的基本单元,拥有自己的独立空间和资源。
1.1.2每个进程都有一个唯一的PID(进程标识符)来标识。
1.2进程间通信:
1.2.1进程不是孤立的,它们之间需要进行信息交互。
1.2.2可以使用multiprocessing模块的Queue实现进程间的数据传递。Queue是一个由操作系统开辟的消息队列空间。
1.3Queue的方法:
1.3.1put(item, block, timeout):将item写入消息队列。
1.3.2get(block, timeout):
1.4进程池Pool:
1.4.1用于管理多个进程的执行。
1.4.2方法包括apply_async(非阻塞方式调用函数)、close(关闭进程池)、join(等待进程池中的进程执行完毕)和terminate(立即终止所有任务)。
2线程:
2.1定义:
2.1.1线程是进程的实体,比进程更小的能独立运行的基本单位。
2.1.2线程基本不拥有系统资源,但共享其所属进程的资源。
2.2线程创建:
2.2.1使用threading.Thread类创建线程,可以指定线程组、要执行的方法、线程名等参数,这是比较常见的线程:
2.3线程的方法:
2.3.1isAlive():
2.3.2getName() / setName(name):
2.3.3isDaemon() / setDaemon(bool):
2.3.4start():启动线程。
2.3.5join():
2.4关于主线程和子线程:
2.4.1主线程:
2.4.2子线程:
2.5守护线程与非守护线程:
2.5.1非守护线程:
2.5.2守护线程:
3关于线程和进程的比较
3.1.资源占用:
3.2通信方式:
3.3并发性:
3.4稳定性:
3.5使用场景:
结语:
前言:
在前面我们已经学过了关于并发编程和和并行的关系,今天我要分享的就是关于进程和线程的内容,进程和线程是操作系统中两个非常重要的概念,它们在程序执行和资源管理方面有着不同的特点和用途.
1进程:
1.1定义:
1.1.1进程是操作系统分配资源的基本单元,拥有自己的独立空间和资源。
1.1.2每个进程都有一个唯一的PID(进程标识符)来标识。
1.2进程间通信:
1.2.1进程不是孤立的,它们之间需要进行信息交互。
1.2.2可以使用multiprocessing
模块的Queue
实现进程间的数据传递。Queue
是一个由操作系统开辟的消息队列空间。
1.3Queue的方法:
1.3.1put(item, block, timeout)
:将item写入消息队列。
- 如果block为True且没有设置timeout,队列满时程序会被阻塞。
- 如果设置了timeout,队列满时会等待timeout秒,之后若仍无空间则抛出
Queue.full
异常。 - 如果block为False且队列满,立即抛出
Queue.full
异常
1.3.2get(block, timeout)
:
从消息队列中获取一条信息。
1.3.1
如果block为True且没有设置timeout,队列空时程序会被阻塞。
1.3.2
如果设置了timeout,队列空时会等待timeout秒,之后若仍无消息则抛出queue.empty
异常。
1.3.3
如果block为False且队列空,立即抛出queue.empty
异常。
qsize()
:返回队列中的消息数量。empty()
:如果队列为空,返回True。full()
:如果队列满了,返回True。
1.4进程池Pool:
1.4.1用于管理多个进程的执行。
1.4.2方法包括apply_async
(非阻塞方式调用函数)、close
(关闭进程池)、join
(等待进程池中的进程执行完毕)和terminate
(立即终止所有任务)。
2线程:
2.1定义:
2.1.1线程是进程的实体,比进程更小的能独立运行的基本单位。
2.1.2线程基本不拥有系统资源,但共享其所属进程的资源。
2.2线程创建:
2.2.1使用threading.Thread
类创建线程,可以指定线程组、要执行的方法、线程名等参数,这是比较常见的线程:
threading.Tread(group, target, name, args, kwargs)
group:线程组
target:要执行的方法
name:线程名,默认thread-N
args/kwargs:传入给函数的参数
2.3线程的方法:
2.3.1isAlive()
:
返回线程是否还在运行。
2.3.2getName()
/ setName(name)
:
获取/设置线程名。
2.3.3isDaemon()
/ setDaemon(bool)
:
判断/设置是否为守护线程(后台线程)。默认为False,即前台线程。当主线程执行完毕后,守护线程会随之停止,而前台线程会继续执行直到完成。
2.3.4start()
:启动线程。
2.3.5join()
:
等待调用该方法的线程执行完毕。
2.4关于主线程和子线程:
2.4.1主线程:
程序启动时运行的线程称为主线程。
2.4.2子线程:
新创建的线程称为子线程或前台线程。
子线程的状态依赖于它所在的进程。如果进程没有退出,子线程能够正常运行;如果进程退出,所有线程(包括子线程)都会退出。但是,这通常取决于线程是否是守护线程以及操作系统的具体行为。在某些情况下,即使主线程结束,子线程也可能继续执行直到它们自己完成或被显式终止。然而,在Python中,如果主线程结束并且没有其他非守护线程在运行,整个进程通常会终止,不管其他守护线程是否已经完成。这是因为Python解释器在所有非守护线程完成后退出,这通常意味着主线程完成后退出。但请注意,这个行为可能依赖于具体的Python实现和平台。因此,在设计多线程程序时应该明确考虑线程的生命周期和同步机制以避免未定义的行为或资源泄漏等问题。
2.5守护线程与非守护线程:
在Python中,线程可以是守护线程或非守护线程。这是通过线程对象的setDaemon(bool)
方法来设置的。如果设置为True
,则该线程是守护线程;如果设置为False
,则是非守护线程。默认情况下,新创建的线程是非守护线程。
2.5.1非守护线程:
当程序中存在非守护线程时,主线程结束时并不会立即导致整个Python程序退出。相反,Python会等待所有非守护线程完成执行后才结束整个程序。
2.5.2守护线程:
守护线程是一种在后台运行的线程。当程序中只剩下守护线程时,Python程序会退出,不会等待守护线程完成。换句话说,守护线程在主线程结束时会被强制终止,即使它们还没有完成执行
3关于线程和进程的比较
3.1.资源占用:
进程占用独立的内存空间和系统资源,而线程共享所在进程的内存空间和资源。因此,进程的创建、销毁和切换的开销较大,而线程的开销较小。
3.2通信方式:
进程之间需要通过IPC机制进行通信,相对复杂;而线程之间可以通过共享内存等方式进行通信,相对简单。
3.3并发性:
进程和线程都具有并发性,可以在同一时间段内并发执行。但是,由于线程共享进程的内存空间和资源,因此线程之间的调度和同步更加复杂。
3.4稳定性:
由于进程具有独立性,因此一个进程的崩溃不会影响其他进程;而线程之间缺乏独立性,一个线程的崩溃可能导致整个进程的崩溃。因此,在稳定性方面,进程相对更优。
3.5使用场景:
对于需要独立运行、资源占用较大或需要频繁创建和销毁的任务,适合使用进程;而对于需要共享资源、轻量级或需要高并发执行的任务,适合使用线程。在实际应用中,可以根据具体需求选择使用进程或线程。
结语:
好了,关于进程和线程我们今天就先分享到这里了,其实关于进程和线程的选择还是需要具体情况具体分析,这两者都给有优劣,希望大家在操作时可以明确自己想实现的效果,同时,也欢迎大家给我的文章斧正,有什么建议都可以提,同时也希望这篇文章能够帮助你对线程和进程有一个更加清楚的认识。