文章目录
在Python中,有几种方法可以处理并行执行任务。其中,Process、Thread和ThreadPoolExecutor是常用的几种方式。
1 Process:
multiprocessing模块提供了Process类,它允许你在多进程环境中并行执行任务。每个进程都有自己的内存空间和Python解释器,因此它们可以独立地运行。
from multiprocessing import Process
def func(name):
print('Hello', name)
if __name__ == '__main__':
p1 = Process(target=func, args=('Alice',))
p2 = Process(target=func, args=('Bob',))
p1.start()
p2.start()
p1.join()
p2.join()
2 Thread:
threading模块提供了Thread类,它允许你在多线程环境中并行执行任务。线程共享同一个进程的内存空间,因此它们之间的通信比进程要快。
from threading import Thread
def func(name):
print('Hello', name)
if __name__ == '__main__':
t1 = Thread(target=func, args=('Alice',))
t2 = Thread(target=func, args=('Bob',))
t1.start()
t2.start()
t1.join()
t2.join()
3 ThreadPoolExecutor:
concurrent.futures模块提供了ThreadPoolExecutor类,它是一个线程池执行器,允许你在多线程环境中并行执行任务。与手动创建线程不同,ThreadPoolExecutor管理线程池,并在需要时分配任务。这使得代码更简洁,更容易管理。
from concurrent.futures import ThreadPoolExecutor
def func(name):
print('Hello', name)
if __name__ == '__main__':
with ThreadPoolExecutor(max_workers=2) as executor:
executor.submit(func, 'Alice')
executor.submit(func, 'Bob')
4 各种方式的优缺点:
这三种方式各有优缺点。
- 使用Process时,每个进程都有自己的内存空间和Python解释器,因此它们是相互独立的。但是,进程之间的通信比线程更复杂,且创建进程的开销也更大。
- -使用Thread时,线程共享同一个进程的内存空间,因此它们之间的通信更快。但是,Python的全局解释器锁(GIL)限制了同一时间只有一个线程可以执行Python字节码。
-
- 使用ThreadPoolExecutor时,它提供了简单、易用的接口来管理线程池,并自动分配任务。但是,如果任务数量超过了线程池的大小,那么任务会被排队等待执行。
5 线程与进程的结束方式
5.1 线程结束的几种方式
- 使用return语句:在Python中,你可以在线程函数中使用return语句来结束线程。当线程函数执行到return语句时,它将退出并释放资源。
import threading
def my_thread():
print("Thread is running...")
return
t = threading.Thread(target=my_thread)
t.start()
t.join()
- 异常处理:如果在线程函数中抛出异常,并且没有被捕获和处理,那么线程将会结束。你可以通过捕获异常来控制线程的结束。
import threading
def my_thread():
try:
print("Thread is running...")
# Some code that may raise an exception
except Exception as e:
print("Exception occurred:", e)
return
t = threading.Thread(target=my_thread)
t.start()
t.join()
- 使用线程结束标志:你可以设置一个标志来指示线程何时应该结束。当标志被设置为True时,线程可以检查该标志并决定是否退出。
import threading
import time
class MyThread(threading.Thread):
def __init__(self):
super().__init__()
self._stop_event = threading.Event()
def run(self):
while not self._stop_event.is_set():
print("Thread is running...")
time.sleep(1) # Pause for a while to demonstrate the stop event.
if self._stop_event.is_set():
break # Exit the loop if stop event is set.
# Continue with your thread's logic here...
def stop(self):
self._stop_event.set() # Set the stop event to true.
self.join() # Wait for the thread to finish.
print("Thread has been stopped.")
5.2 进程的结束方式
- 使用sys.exit():这是Python标准库中sys模块提供的一个函数,可以用来退出程序。
- 使用os._exit():这是Python底层的一个函数,它与sys.exit()类似,但更直接地结束进程。
- 使用raise SystemExit:这是Python内置的一个异常,可以用来表示程序需要退出。
- 使用os.kill():如果需要从外部杀死一个Python进程,可以使用这个函数。
import os
import time
pid = os.getpid() # 获取当前进程的ID
time.sleep(5) # 让进程运行一段时间
os.kill(pid, 9) # 使用9号信号杀死进程
6 应用场景效率对比
-
多线程在IO密集型的操作下似乎也没有很大的优势(也许IO操作的任务再繁重一些就能体现出优势),在CPU密集型的操作下明显地比单线程线性执行性能更差,但是对于网络请求这种忙等阻塞线程的操作,多线程的优势便非常显著了
-
多进程无论是在CPU密集型还是IO密集型以及网络请求密集型(经常发生线程阻塞的操作)中,都能体现出性能的优势。不过在类似网络请求密集型的操作上,与多线程相差无几,但却更占用CPU等资源,所以对于这种情况下,我们可以选择多线程来执行