我来详细讲解一下“Python线程的几种创建方式详解”的攻略。
简介
Python线程是指在一个程序内部,同时执行多个不同的线程以完成不同任务的一种机制。使用线程能够提高程序的运行效率,因为它可以同时执行多个任务,使得程序可以在某些任务被阻塞时,继续执行其他任务。
Python线程的创建方式有以下几种:
- 使用
threading.Thread
类创建线程对象 - 继承
threading.Thread
类创建线程类 - 使用
_thread
或thread
模块创建线程 - 使用
concurrent.futures
模块创建线程池
接下来,我们将逐个讲解这几种创建方式。
使用threading.Thread
类创建线程对象
使用threading.Thread
类创建线程对象是最常用的方式之一。创建线程的过程如下所示:
- 定义一个函数,代表线程要执行的任务
- 创建线程对象,将要执行的任务作为参数传递给线程对象
- 调用
start
方法,启动线程
import threading
def print_numbers():
for i in range(10):
print(threading.current_thread().getName(), i)
t1 = threading.Thread(target=print_numbers)
t2 = threading.Thread(target=print_numbers)
t1.start()
t2.start()
在上面的代码中,我们定义了一个print_numbers
函数,它用于打印当前线程的名称和0-9
之间的数字。
接着,我们创建了两个线程对象t1
和t2
,并将print_numbers
函数作为参数传递给线程对象。最后,我们分别启动了这两个线程。
输出结果如下所示:
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-1 5
Thread-1 6
Thread-1 7
Thread-1 8
Thread-1 9
Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4
Thread-2 5
Thread-2 6
Thread-2 7
Thread-2 8
Thread-2 9
我们可以看到,print_numbers
函数在两个线程中交替执行,每个线程打印出了0-9
之间的数字。
继承threading.Thread
类创建线程类
虽然可以使用上一种方法创建线程,但在处理复杂业务流程时,建议使用类继承的方式进行创建。创建线程的过程如下所示:
- 继承
threading.Thread
类,并重写run
方法 - 创建线程类对象
- 调用
start
方法,启动线程
import threading
class MyThread(threading.Thread):
def __init__(self, name, count):
threading.Thread.__init__(self)
self.name = name
self.count = count
def run(self):
for i in range(self.count):
print(self.name, i)
t1 = MyThread("Thread-1", 5)
t2 = MyThread("Thread-2", 5)
t1.start()
t2.start()
在上面的代码中,我们首先定义了一个MyThread
类,继承自threading.Thread
。然后,重写了run
方法,该方法代表线程要执行的任务。MyThread
类接收两个参数:name
代表线程名称,count
代表打印数字的个数。
接下来,我们创建了两个MyThread
对象,并传入了不同的线程名称和打印数字的个数。最后,我们分别启动了这两个线程。
输出结果如下所示:
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4
可以看到,MyThread
对象中的run
方法在两个线程中交替执行,每个线程打印出了指定个数的数字。
使用_thread
或thread
模块创建线程
_thread
是Python标准库中最低级别的模块之一,可以创建非常轻量级的线程。但是,由于它的使用复杂度较高,大部分开发者都会选择使用threading
模块。如果想要了解更多有关于_thread
模块的信息,请访问官方文档了解。
下面我们来看看如何使用thread
模块创建线程。创建线程的过程如下所示:
- 定义一个函数,代表线程要执行的任务
- 调用
start_new_thread
方法,启动线程
import _thread
import time
def print_numbers(threadName):
for i in range(10):
print(threadName, i)
time.sleep(1)
try:
_thread.start_new_thread(print_numbers, ("Thread-1",))
_thread.start_new_thread(print_numbers, ("Thread-2",))
except:
print("Error: 无法启动线程")
在上面的代码中,我们定义了一个print_numbers
函数,用于打印当前线程名称和0-9
之间的数字。该函数接收一个threadName
参数,代表线程名称。
我们使用try
和except
来处理启动线程的异常,调用_thread.start_new_thread
方法启动两个线程。start_new_thread
方法接收两个参数,第一个参数是线程要执行的函数名,第二个参数是一个元组,包含函数参数。
输出结果如下所示:
Thread-1 0
Thread-2 0
Thread-1 1
Thread-2 1
Thread-1 2
Thread-2 2
Thread-2 3
Thread-1 3
Thread-1 4
Thread-2 4
Thread-1 5
Thread-2 5
Thread-1 6
Thread-2 6
Thread-2 7
Thread-1 7
Thread-1 8
Thread-2 8
Thread-1 9
Thread-2 9
可以看到,print_numbers
函数在两个线程中交替执行,每个线程打印出了0-9
之间的数字。
使用concurrent.futures
模块创建线程池
concurrent.futures
是Python 3.2新增的一组标准库,用于实现异步编程。它提供了一个ThreadPoolExecutor
类,可以很方便地创建线程池,执行异步任务。创建线程池的过程如下所示:
- 创建
ThreadPoolExecutor
对象 - 使用
submit
方法提交任务,并获取Future
对象 - 调用
add_done_callback
方法设置回调函数 - 调用
shutdown
方法,等待所有任务执行完成
import concurrent.futures
import time
def print_numbers(threadName):
for i in range(10):
print(threadName, i)
time.sleep(1)
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
future1 = executor.submit(print_numbers, "Thread-1")
future2 = executor.submit(print_numbers, "Thread-2")
# 设置回调函数
def callback(future):
print("任务执行完成:", future.result())
future1.add_done_callback(callback)
future2.add_done_callback(callback)
在上面的代码中,我们定义了一个print_numbers
函数,用于打印当前线程名称和0-9
之间的数字。该函数接收一个threadName
参数,代表线程名称。
我们使用with
语句创建了一个ThreadPoolExecutor
对象,并设置最大线程数为2
。接着,调用executor.submit
方法提交了两个任务,并获取返回的Future
对象。通过add_done_callback
方法来设置任务执行完成后的回调函数。
最后,我们调用shutdown
方法来等待所有任务执行完成。
输出结果如下所示:
Thread-1 0
Thread-2 0
Thread-1 1
Thread-2 1
Thread-1 2
Thread-2 2
Thread-2 3
Thread-1 3
Thread-1 4
Thread-2 4
Thread-1 5
Thread-2 5
Thread-1 6
Thread-2 6
Thread-2 7
Thread-1 7
Thread-1 8
Thread-2 8
Thread-1 9
Thread-2 9
任务执行完成: None
任务执行完成: None
可以看到,print_numbers
函数在两个线程中交替执行,每个线程打印出了0-9
之间的数字。任务执行完成后,我们设置的回调函数也成功被调用。
总结
以上就是Python线程的几种创建方式的详细攻略。在使用线程时,需要注意锁的使用,以避免出现线程安全问题。我们可以使用threading.Lock
类来创建锁对象,在多个线程同时访问共同资源时,使用该锁对象可以保证线程安全。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python线程的几种创建方式详解 - Python技术站