1、線程的介紹
2、線程與進程的區別
例子。
import threading
import time
def fun(num):
print("線程執行%d"%num)
time.sleep(2)
# 執行5個形參
for i in range(5):
t = threading.Thread(target=fun, args=(i+1,)) # 設置線程
t.start() # 啓動線程
3、 查看幫助信息及參數信息
import threading
print(help(threading.Thread))
4、 查看當前形參數量
# coding=utf-8
import threading
from time import sleep, ctime
def sing():
for i in range(3):
print("傻不傻%d" % i)
sleep(1)
def dance():
for i in range(3):
print("????%d" % i)
sleep(1)
if __name__ == '__main__':
print('___開始___%s' % ctime()) # 獲取當前時間,字符串表示沒,讀格式
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
while True:
length = len(threading.enumerate())
print("當前運行的線程數爲:%d" % length)
if length<=1: # 等於就只剩一個主線程,說明副線程都運行完了
break
sleep(0.5)
5、子類化線程類
# coding=utf-8
import threading
import time
class MyThread(threading.Thread):
def __init__(self, num, str1):
super().__init__()
self.num = num
self.str1 = str1
def run(self):
for i in range(3):
time.sleep(1)
msg = "I am " + self.name + " @" + str(i) + " num:" + str(self.num) + "str1:" + self.str1 # name屬性中報錯的是當前線程的
print(msg)
if __name__ == '__main__':
t = MyThread(10, "abc")
t.start()
6、線程的幾種狀態
7、線程共享全局變量
# coding=utf8
from threading import Thread
import time
g_num = 100
def work1():
global g_num
for i in range(3):
g_num += 1
print("---in work1.g_num is %d---" % g_num)
def work2():
global g_num
print("---in work2.g_num is %d---" % g_num)
print("----創建線程之前g_num is %d---" % g_num)
t1 = Thread(target=work1())
t1.start()
# 延遲一會,保證線程中的事情做完
t2 = Thread(target=work2())
t2.start()
8、用傳參的方式使用全局變量
例子一;全局變量爲不可變對象
# coding=utf8
from threading import Thread
import time
g_num = 100
def work1(num):
for i in range(3):
num += 1
print("---in work1.g_num is %d---" % num)
def work2(num):
print("---in work2.g_num is %d---" % num)
print("----創建線程之前g_num is %d---" % g_num)
t1 = Thread(target=work1, args=(g_num,))
t1.start()
# 延遲一會,保證線程中的事情做完
t2 = Thread(target=work2, args=(g_num,))
t2.start()
print("----創建線程之後g_num is %d---" % g_num)
輸出:
----創建線程之前g_num is 100---
---in work1.g_num is 101---
---in work1.g_num is 102---
---in work1.g_num is 103---
---in work2.g_num is 100---
----創建線程之後g_num is 100---
第二個例子:全局變量爲可變對象
# coding=utf8
from threading import Thread
import time
g_num = [11, 22, 33]
def work1(num):
for i in range(3):
num.append(44)
print("---in work1.g_num is %s---" % num)
def work2(num):
print("---in work2.g_num is %s---" % num)
print("----創建線程之前g_num is %s---" % g_num)
t1 = Thread(target=work1, args=(g_num,))
t1.start()
# 延遲一會,保證線程中的事情做完
t2 = Thread(target=work2, args=(g_num,))
t2.start()
print("----創建線程之後g_num is %s---" % g_num)
輸出
----創建線程之前g_num is [11, 22, 33]---
---in work1.g_num is [11, 22, 33, 44]---
---in work1.g_num is [11, 22, 33, 44, 44]---
---in work1.g_num is [11, 22, 33, 44, 44, 44]---
---in work2.g_num is [11, 22, 33, 44, 44, 44]---
----創建線程之後g_num is [11, 22, 33, 44, 44, 44]---
9、線程同步問題
例子1
coding=utf8
import threading
import time
g_num = 0
def work1():
global g_num
for i in range(10):
g_num += 1
for i in range(2):
t = threading.Thread(target=work1)
t.start()
print("----創建線程之後g_num is %s---" % g_num)
輸出
----創建線程之後g_num is 20---
例子2
把上面代碼中的 for i in range(10):
改成 for i in range(1000000):
輸出
----創建線程之後g_num is 219002---
按理說應該輸出2000000,但是結果不是,這是因爲2個線程之間
進程在運行的時候,數據是放在內存裏的,而CPU在運算的時候,數據是要讀在數據的寄存器裏的(CPU中有很多寄存器),然後再在寄存器中對數據進行操作,最後再寫會內存裏。
在上面代碼中
10、線程同步-給線程加鎖
創建鎖
mutex = threading.Lock()
鎖定
mutex.acquire([blocking])
如果沒有設定block爲True,則當前線程會堵塞,直到獲取這個鎖爲止(如果沒有指定,默認爲True)
如果設定blocking爲False,則當前線程不會堵塞
釋放
mutex.relesse()
例子:加了一個互斥鎖,成功輸出結果
# coding=utf8
import threading
import time
class Task1(threading.Thread):
def run(self):
while True:
if lock1.acquire():
print("---Task1---")
time.sleep(1)
lock2.release()
class Task2(threading.Thread):
def run(self):
while True:
if lock2.acquire():
print("---Task2---")
time.sleep(1)
lock3.release()
class Task3(threading.Thread):
def run(self):
while True:
if lock3.acquire():
print("---Task3---")
time.sleep(3)
lock1.release()
lock1 = threading.Lock()
lock2 = threading.Lock()
lock2.acquire()
lock3 = threading.Lock()
lock3.acquire()
t1 = Task1()
t2 = Task2()
t3 = Task3()
t1.start()
t2.start()
t3.start()
通過3把鎖固定線程執行的順序,執行完線程t1,然後執行線程t2,然後執行線程t3,然後依次循環。
12、queue的使用
# coding=utf8
import threading
import time
from queue import Queue
class Producter(threading.Thread):
def run(self):
while True:
if queue.qsize() < 1000:
for x in range(100):
msg = "產品" + str(x)
print("%s創建了%s"%(self.name, msg))
queue.put(msg)
time.sleep(1)
class Consumer(threading.Thread):
def run(self):
while True:
if queue.qsize() > 100:
for x in range(3):
msg = queue.get()
print("%s消費了%s"%(self.name, msg))
time.sleep(0.5)
queue = Queue()
for i in range(500):
msg = "產品" + str(i)
queue.put("msg")
for i in range(2):
t = Producter()
t.start()
for i in range(5):
c = Consumer()
c.start()
13、ThreadLocal 變量