在Python中,多线程编程是并发执行任务的重要方式,特别是在需要执行多个独立任务而无需等待每个任务完成的情况下。Python提供了`thread`和`threading`两个模块来支持多线程,但通常推荐使用功能更丰富的`threading`模块。本篇文章主要探讨了在`threading`模块中启动线程的两种主要方法。
### 1. 将函数传递进Thread对象
这种方法的核心是创建`threading.Thread`对象,并将要执行的函数作为参数传入。`target`参数指定要运行的函数,`args`参数则用于传递函数所需的参数。以下是一个示例:
```python
import threading
def thread_fun(num):
for n in range(0, int(num)):
print(f"I come from {threading.currentThread().getName()}, num: {n}")
def main(thread_num):
thread_list = []
for i in range(0, thread_num):
thread_name = f"thread_{i}"
thread_list.append(threading.Thread(target=thread_fun, name=thread_name, args=(20,)))
for thread in thread_list:
thread.start()
for thread in thread_list:
thread.join()
if __name__ == "__main__":
main(3)
```
在这个例子中,`main`函数创建了3个线程,每个线程都会执行`thread_fun`函数,参数为20。`start()`方法启动线程,而`join()`方法则确保主线程等待所有子线程执行完毕后再继续执行。
### 2. 继承自threading.Thread类
另一种启动线程的方式是创建一个新的类,该类继承自`threading.Thread`,并在新类中重写`run`方法。`run`方法将作为线程执行的入口点。下面是一个简单的例子:
```python
import threading
class MyThread(threading.Thread):
def __init__(self):
super().__init__()
def run(self):
print(f"I am {self.name}")
if __name__ == "__main__":
for _ in range(0, 5):
t = MyThread()
t.start()
```
在这个例子中,我们创建了一个名为`MyThread`的新类,它继承自`threading.Thread`。`run`方法包含了线程要执行的任务,即打印线程的名字。在主程序中,创建并启动了5个这样的线程。
### 线程控制
在后续的讨论中,将涉及到如何控制线程的行为。例如:
- **子线程的退出**:线程一旦启动,通常会一直运行直到其`run`方法结束。如果需要提前结束线程,可以使用`threading.Event`对象来设置一个事件标志,线程在检查到这个标志时自行终止。
- **子线程是否存活**:可以使用`is_alive()`方法检查线程是否仍在运行。
- **设置守护线程(Daemon)**:通过设置线程的`daemon`属性为`True`,可以将线程标记为守护线程。守护线程不会阻止进程的退出,即使它们仍在运行。默认情况下,主线程是非守护线程,而由非守护线程创建的子线程也将是非守护线程。
了解这些基本的线程控制技巧,可以帮助开发者更好地管理和调度多线程程序,提高程序的并发性能和资源利用率。在实际编程中,还需要考虑线程同步问题,如使用锁、条件变量等工具,以避免数据竞争和死锁等并发问题。