# 0x01 线程基础

## 线程创建

Python中创建的线程实例会在它们自己所属的**系统级线程**(Linux线程或Windows线程)中执行, 这些线程完全由**操作系统**来管理, 一旦启动后, 线程就开始独立地运行, 直到目标函数返回为止.

Python中创建线程有两种方式.

### 直接创建线程对象

```python
import time
import threading

def count_down(n):
    while n > 0:
        print("T-minus", n)
        n -= 1
        time.sleep(1)

t = threading.Thread(target=count_down, args=(9,))
t.start()
t.join()
```

### 继承Thread类

```python
class CountDownThread(threading.Thread):
    def __init__(self, n):
        super().__init__()
        self.n = n

    def run(self):
        while self.n > 0:
            print("T-minus", self.n)
            self.n -= 1
            time.sleep(1)

c = CountDownThread(9)
c.start()
c.join()
```

通过重构`threading`中`Thread`类的`run`方法实现, 其余的操作和直接创建的`Thread`对象操作相同. 但并不推荐这种方式, 因为同样的功能函数可能也希望用于多进程, 甚至分布式的场景. 而这种对象方法只能使用在多线程中.

## 守护线程

线程分为:

* 守护线程/后台线程: 在主线程结束后, 会跟随主线程自动销毁
* 非守护线程/前台线程: 主线程结束后, 仍然会运行到结束

设置线程是否是守护线程有两种方式:

### 创建时设置

通过显示地对`daemon`参数传参. 默认为`False`, 即非守护线程.

```python
t = threading.Thread(target=count_down, args=(9,), daemon=True)
```

### 设置线程对象属性

对实例化的线程对象的`daemon`属性进行设置, 需要在调用`start()`方法之前进行设置.

```python
t = threading.Thread(target=count_down, args=(9,))
print(t.isDaemon())
t.daemon = True
print(t.isDaemon())
```

输出为:

```
False
True
```

## 线程对象属性和方法

常用的有以下几种:

* **t.is\_alive()**: 线程是否在运行中
* **t.isDaemon()**: 线程是否是守护线程
* **t.setDaemon(bool)**: 设置线程类型, 是否为守护线程, 等价于`t.daemon = True/False`
* **t.setName(name)**: 设置线程名称
* **t.getName()**: 获取线程名称
* **t.start()**: 启动线程
* **t.join(\[timeout])**: 连接(join)到线程上, 相当于阻塞主线程, 等待该线程执行结束. 可以设置超时参数

## threading包其他方法

* **threading.current\_thread()**: 返回当前所在线程的线程对象
* **threading.enumerate()**: 返回一个`list`, 包含当前解释器中所有正在运行的线程对象
* **threading.activeCount()**: 返回当前解释器中正在运行的线程的数量
* **threading.TIMEOUT\_MAX**: 设置threading全局的超时时间

  ```python
  threading.TIMEOUT_MAX
  ```

  输出为:

  ```
  4294967.0
  ```
