龙空技术网

Python多线程入门教程

积极的python程序猿 524

前言:

如今我们对“python多线程join”大约比较注意,你们都想要了解一些“python多线程join”的相关知识。那么小编同时在网络上收集了一些对于“python多线程join””的相关文章,希望同学们能喜欢,大家快快来了解一下吧!

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

图片来源于网络

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

图片来源于网络

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

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

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

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

使用threading模块

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

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

下面是一个简单的例子:

import threadingimport 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)等,它们可以用来解决线程之间的同步和通信问题。如果你想了解更多,请参考官方文档:

使用concurrent.futures模块

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

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

下面是一个简单的例子:

import concurrent.futuresimport time# 定义一个函数来封装要执行的任务def say_hello(name):    print(f"Hello, {name}!")    time.sleep(1) # 模拟耗时操作    return f"Bye, {name}!"# 创建一个线程池对象,并指定最大线程数为2executor = 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)等,它们可以用来处理更复杂和灵活的多线程场景。如果你想了解更多,请参考官方文档:

总结

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

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

标签: #python多线程join #python多线程join之后一直不结束 #python的join线程 #python子线程调用主线程方法函数