Python多线程入门教程

liftword1个月前 (03-31)技术文章7

Python是一门非常流行和强大的编程语言,它有很多优点,比如简洁、易读、丰富的库等。但是,Python也有一些缺点,其中之一就是它的多线程支持不太理想。


多线程是什么呢?简单来说,就是让一个程序可以同时执行多个任务,从而提高效率和性能。比如,你可以在一个线程里下载一个文件,同时在另一个线程里处理用户的输入,这样就不会让用户感觉到卡顿或者等待。


那么,为什么Python的多线程支持不太理想呢?这主要是因为Python有一个叫做全局解释器锁(Global Interpreter Lock,简称GIL)的机制,它保证了同一时刻只有一个线程可以执行Python字节码,这样可以避免一些数据竞争和内存管理的问题,但是也限制了Python的并发能力。

那么,Python的多线程还有用吗?当然有用,只是要根据不同的场景来选择合适的方法。如果你的程序主要是CPU密集型的,也就是说需要大量计算的,那么Python的多线程可能并不会带来太大的提升,甚至可能会降低性能,因为线程之间还要切换和同步。这种情况下,你可能更适合使用多进程或者其他语言来实现。

但是,如果你的程序主要是IO密集型的,也就是说需要大量等待外部资源的,比如网络、文件、数据库等,那么Python的多线程就可以发挥作用了,因为在等待的过程中,其他线程可以继续执行,从而提高效率和响应速度。这种情况下,你可以使用Python自带的threading模块或者第三方的concurrent.futures模块来实现。

接下来,我们就来看看如何使用这两个模块来实现Python的多线程。

使用threading模块

threading模块是Python自带的一个基础模块,它提供了一些低级别的多线程操作,比如创建、启动、终止、同步和通信等。使用threading模块的基本步骤如下:

  1. 导入threading模块
  2. 定义一个函数或者一个类来封装要执行的任务
  3. 创建一个或者多个threading.Thread对象,并传入函数或者类作为参数
  4. 调用start方法来启动线程
  5. 调用join方法来等待线程结束(可选)

下面是一个简单的例子:

import threading
import time

# 定义一个函数来封装要执行的任务
def say_hello(name):
    print(f"Hello, {name}!")
    time.sleep(1) # 模拟耗时操作

# 创建两个线程对象,并传入不同的参数
t1 = threading.Thread(target=say_hello, args=("Alice",))
t2 = threading.Thread(target=say_hello, args=("Bob",))

# 启动两个线程
t1.start()
t2.start()

# 等待两个线程结束
t1.join()
t2.join()

print("Done!")

运行结果:

Hello, Alice!
Hello, Bob!
Done!

可以看到,两个线程几乎同时开始执行,并且在主线程结束之前都结束了。这就是使用threading模块实现多线程的基本方法。

当然,threading模块还提供了一些其他的功能,比如锁(Lock)、信号量(Semaphore)、事件(Event)、条件变量(Condition)等,它们可以用来解决线程之间的同步和通信问题。如果你想了解更多,请参考官方文档:
https://docs.python.org/3/library/threading.html

使用concurrent.futures模块

concurrent.futures模块是Python 3.2以后新增的一个高级模块,它提供了一个更简洁和抽象的多线程接口,比如线程池(ThreadPoolExecutor)、异步执行(submit)、回调函数(add_done_callback)等。使用concurrent.futures模块的基本步骤如下:

  1. 导入concurrent.futures模块
  2. 定义一个函数或者一个类来封装要执行的任务
  3. 创建一个concurrent.futures.ThreadPoolExecutor对象,并指定最大线程数
  4. 调用submit方法来提交任务,并获取一个Future对象
  5. 调用result方法来获取任务的返回值,或者调用add_done_callback方法来添加回调函数
  6. 调用shutdown方法来关闭线程池(可选)

下面是一个简单的例子:

import concurrent.futures
import time

# 定义一个函数来封装要执行的任务
def say_hello(name):
    print(f"Hello, {name}!")
    time.sleep(1) # 模拟耗时操作
    return f"Bye, {name}!"

# 创建一个线程池对象,并指定最大线程数为2
executor = concurrent.futures.ThreadPoolExecutor(max_workers=2)

# 提交两个任务,并获取两个Future对象
f1 = executor.submit(say_hello, "Alice")
f2 = executor.submit(say_hello, "Bob")

# 获取任务的返回值
print(f1.result())
print(f2.result())

# 关闭线程池
executor.shutdown()

print("Done!")

运行结果:

Hello, Alice!
Hello, Bob!
Bye, Alice!
Bye, Bob!
Done!

可以看到,两个任务被提交到线程池中,并且在主线程结束之前都返回了结果。这就是使用concurrent.futures模块实现多线程的基本方法。

当然,concurrent.futures模块还提供了一些其他的功能,比如批量提交任务(map)、取消任务(cancel)、等待任务完成(wait)、超时设置(timeout)等,它们可以用来处理更复杂和灵活的多线程场景。如果你想了解更多,请参考官方文档:
https://docs.python.org/3/library/concurrent.futures.html

总结

Python的多线程是一个有用但也有限制的功能,它可以用来提高IO密集型程序的效率和响应速度,但是对于CPU密集型程序可能并不适合。Python提供了两个主要的多线程模块:threading和concurrent.futures,它们分别提供了不同层次和抽象度的多线程操作。你可以根据你的需求和喜好来选择合适的模块和方法来实现Python的多线程。

希望这篇文章对你有所帮助,如果你有任何问题或者建议,请在评论区留言。谢谢!

相关文章

python笔记47:多线程详解

主要内容:小目标:掌握多线程;主要内容:线程类使用,多线程使用;1. 线程基本概念线程概念:线程是轻量级进程,是操作系统能够进行运算调度的最小单位;线程依赖进程资源,是进程中的实际运作单位;一个进程中...

Python中的多线程详解,让你的程序飞起来!

Python是一门高级编程语言,拥有简单易用、面向对象、可扩展等优点,因此被广泛应用于各种领域。但是在Python中,由于GIL(全局解释器锁)的存在,导致了多线程的效率不高。但是,对于某些IO密集型...

Python并发编程(3)——Python多线程详解介绍

左手编程,右手年华。大家好,我是一点,关注我,带你走入编程的世界。公众号:一点sir,关注领取python编程资料Python 的多线程入门是非常简单的,直接导入threading模块就可以开始多线程...

Python多线程编程到底怎么玩?核心技巧与注意事项全知道!

在 Python 中,多线程编程主要用于处理 I/O 密集型任务(如网络请求、文件读写、数据库操作等),但由于 全局解释器锁(GIL) 的存在,多线程对 CPU 密集型任务 的性能提升有限(此时建议使...

小白都看懂了,Python 中的线程和进程精讲,建议收藏

目录线程和进程一、 什么是进程 / 线程1、 引论众所周知,CPU是计算机的核心,它承担了所有的计算任务。而操作系统是计算机的管理者,是一个大管家,它负责任务的调度,资源的分配和管理,统领整个计算机硬...

Python多线程

本文重点探究以下几个问题:多线程内存共享线程类获取线程结果方法:join/setDaemon对线程退出的作用线程无法利用多核,不是真正的并发多线程内存共享多个线程访问同一内存变量时,需要通过锁机制来实...