> For the complete documentation index, see [llms.txt](https://tomlin.gitbook.io/bei-shang-zi-guan-python-ke-cheng-2/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tomlin.gitbook.io/bei-shang-zi-guan-python-ke-cheng-2/yi-.-ke-cheng-nei-rong/yi-han-shi/14.-zhi-xing-xu.md).

# 14. 執行緒

## (1) 建立一個執行緒

程式的執行有一個主執行緒. 在主執行緒建立另一個執行緒並啟動它, 整個程式因此有2個執行緒"同時"執行. 所謂的"同時", 是大家分享CPU時間, 交錯執行.

```python
import threading
import time

#-----------------------------
# 執行緒函式
#-----------------------------
def my_function():
    print("開始執行緒")
    for i in range(10):
        print(i)
        time.sleep(1)  #暫停1秒
    print("結束執行緒")


#-----------------------------
# 主程式
#-----------------------------
print("<<主執行緒開始>>")

# 建立一個執行緒物件
my_thread = threading.Thread(target=my_function)

# 啟動執行緒
my_thread.start()

# 等待執行緒完成
my_thread.join()

print("<<主執行緒完成>>")
```

### 執行結果：

```python
<<主執行緒開始>>
開始執行緒
0
1
2
3
4
5
6
7
8
9
結束執行緒
<<主執行緒完成>>
```

## (2) 多個執行緒之間有自己的區域變數

執行緒函式內的變數是由每個執行緒維持自己的一份, 與其他執行緒不互相影響.

```python
import threading
import time

#-----------------------------
# 執行緒函式
#-----------------------------
def my_function():
    print("開始執行緒")
    for i in range(10):
        print(i)
        time.sleep(1)  #暫停1秒
    print(f"結束執行緒")


#-----------------------------
# 主程式
#-----------------------------
print("<<主執行緒開始>>")

# 建立一個執行緒物件
my_thread1 = threading.Thread(target=my_function)
my_thread2 = threading.Thread(target=my_function)

# 啟動執行緒
my_thread1.start()
my_thread2.start()

# 等待執行緒完成
my_thread1.join()
my_thread2.join()

print("<<主執行緒完成>>")
```

### 執行結果：

```python
<<主執行緒開始>>
開始執行緒
0
開始執行緒
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
結束執行緒
結束執行緒
<<主執行緒完成>>
```

## (3) 傳參數給執行緒

```python
import threading
import time

#-----------------------------
# 執行緒函式
#-----------------------------
def my_function(name):
    print(f"開始執行緒{name}")
    for i in range(10):
        print(f'{name}:{i}')
        time.sleep(1)  #暫停1秒
    print(f"結束執行緒{name}")


#-----------------------------
# 主程式
#-----------------------------
print("<<主執行緒開始>>")

# 建立一個執行緒物件
my_thread1 = threading.Thread(target=my_function, args=('Tom',))
my_thread2 = threading.Thread(target=my_function, args=('Mary',))

# 啟動執行緒
my_thread1.start()
my_thread2.start()

# 等待執行緒完成
my_thread1.join()
my_thread2.join()

print("<<主執行緒完成>>")
```

### 執行結果：

```python
<<主執行緒開始>>
開始執行緒Tom
Tom:0
開始執行緒Mary
Mary:0
Tom:1
Mary:1
Tom:2
Mary:2
Mary:3
Tom:3
Tom:4
Mary:4
Tom:5
Mary:5
Tom:6
Mary:6
Tom:7
Mary:7
Tom:8
Mary:8
Tom:9
Mary:9
結束執行緒Tom
結束執行緒Mary
<<主執行緒完成>>
```

## (4) 執行緒之間共用廣域變數

```python
import threading
import time

# 建立一個鎖
lock = threading.Lock()

# 廣域變數
counter=0

#-----------------------------
# 執行緒函式
#-----------------------------
def my_function(name):
    global counter
    print(f"開始執行緒{name}")
    for i in range(10):
        with lock:
            counter+=1
            print(f'{name}:{counter}')
        time.sleep(1)  #暫停1秒
    print(f"結束執行緒{name}")


#-----------------------------
# 主程式
#-----------------------------
print("<<主執行緒開始>>")

# 建立一個執行緒物件
my_thread1 = threading.Thread(target=my_function, args=('Tom',))
my_thread2 = threading.Thread(target=my_function, args=('Mary',))

# 啟動執行緒
my_thread1.start()
my_thread2.start()

# 等待執行緒完成
my_thread1.join()
my_thread2.join()

print("<<主執行緒完成>>")
```

### 執行結果：

```python
<<主執行緒開始>>
開始執行緒Tom
Tom:1
開始執行緒Mary
Mary:2
Tom:3
Mary:4
Mary:5
Tom:6
Mary:7
Tom:8
Tom:9
Mary:10
Mary:11
Tom:12
Mary:13
Tom:14
Tom:15
Mary:16
Mary:17
Tom:18
Mary:19
Tom:20
結束執行緒Mary
結束執行緒Tom
<<主執行緒完成>>
```

## (5) 執行緒與閉包

```python
import threading
import time
import random

#--------------------------
# 取得counter()物件的位址
#--------------------------
def make_counter():
    cnt=0
    def counter():
        nonlocal cnt
        cnt+=1
        return cnt
    
    return counter

#--------------------------
# 執行緒內容的函式
#--------------------------
def my_function(name, counter):
    for i in range(10):
        print(f'{name}->{counter()}')
        time.sleep(random.randint(1,2))

#------------------
# 產生一個閉包
#------------------
counter=make_counter()
        
#------------------
# 產生2個執行緒
#------------------       
my_thread1 = threading.Thread(target=my_function, args=('tom', counter))
my_thread2 = threading.Thread(target=my_function, args=('mary', counter))

#------------------
# 啟動執行緒
#------------------ 
my_thread1.start()  
my_thread2.start()        
```

### 執行結果：

```python
tom->1
mary->2
tom->3
mary->4
tom->5
mary->6
mary->7
tom->8
mary->9
tom->10
tom->11
mary->12
mary->13
tom->14
tom->15
mary->16
tom->17
mary->18
tom->19
mary->20
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tomlin.gitbook.io/bei-shang-zi-guan-python-ke-cheng-2/yi-.-ke-cheng-nei-rong/yi-han-shi/14.-zhi-xing-xu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
