python note 31 多線程

一、應用程序網絡

import threading

print('666')

def func(arg):
    print(arg)


t = threading.Thread(target=func)
t.start()

print('end')

二、線程的使用多線程

import threading

1.線程的基本使用
def func(arg):
    print(arg)

t = threading.Thread(target=func,args=(11,))
t.start()

print(123)
2.主線程默認等子線程執行完畢
import time
def func(arg):
    time.sleep(arg)
    print(arg)

t1 = threading.Thread(target=func,args=(3,))
t1.start()

t2 = threading.Thread(target=func,args=(9,))
t2.start()

print(123)
3.主線程再也不等,主線程終止則全部子線程終止
import time
def func(arg):
    time.sleep(2)
    print(arg)

t1 = threading.Thread(target=func,args=(3,))
t1.setDaemon(True)
t1.start()

t2 = threading.Thread(target=func,args=(9,))
t2.setDaemon(True)
t2.start()

print(123)

4.開發者能夠控制主線程等待子線程(最多等待時間) 
import time
def func(arg):
    time.sleep(0.01)
    print(arg)

print('建立子線程t1')
t1 = threading.Thread(target=func,args=(3,))
t1.start()
# 無參數,讓主線程在這裏等着,等到子線程t1執行完畢,才能夠繼續往下走。
# 有參數,讓主線程在這裏最多等待n秒,不管是否執行完畢,會繼續往下走。
t1.join(2)

print('建立子線程t2')
t2 = threading.Thread(target=func,args=(9,))
t2.start()
t2.join(2) # 讓主線程在這裏等着,等到子線程t2執行完畢,才能夠繼續往下走。

print(123)

4.線程名稱
def func(arg):
    # 獲取當前執行該函數的線程的對象
    t = threading.current_thread()
    # 根據當前線程對象獲取當前線程名稱
    name = t.getName()
    print(name,arg)

t1 = threading.Thread(target=func,args=(11,))
t1.setName('侯明魏')
t1.start()

t2 = threading.Thread(target=func,args=(22,))
t2.setName('劉寧錢')
t2.start()

print(123)

5.線程本質
# 先打印:11?123?
def func(arg):
    print(arg)

t1 = threading.Thread(target=func,args=(11,))
t1.start()
# start 是開始運行線程嗎?不是
# start 告訴cpu,我已經準備就緒,你能夠調度我了。
print(123)


6.補充:面向對象版本的多線程 
# 多線程方式:1 (常見)
def func(arg):
    print(arg)

t1 = threading.Thread(target=func,args=(11,))
t1.start()

# 多線程方式:2
class MyThread(threading.Thread):

def run(self):
    print(11111,self._args,self._kwargs)

t1 = MyThread(args=(11,))
t1.start()

t2 = MyThread(args=(22,))
t2.start()

print('end')

三、多線程socket

import threading

1. 計算密集型多線程無用
v1 = [11,22,33] # +1
v2 = [44,55,66] # 100

def func(data,plus):
    for i in range(len(data)):
        data[i] = data[i] + plus

t1 = threading.Thread(target=func,args=(v1,1))
t1.start()

t2 = threading.Thread(target=func,args=(v2,100))
t2.start()


2. IO操做 多線程有用
import threading
import requests
import uuid

url_list = [
     'https://www3.autoimg.cn/newsdfs/g28/M05/F9/98/120x90_0_autohomecar__ChsEnluQmUmARAhAAAFES6mpmTM281.jpg',
     'https://www2.autoimg.cn/newsdfs/g28/M09/FC/06/120x90_0_autohomecar__ChcCR1uQlD6AT4P3AAGRMJX7834274.jpg',
     'https://www2.autoimg.cn/newsdfs/g3/M00/C6/A9/120x90_0_autohomecar__ChsEkVuPsdqAQz3zAAEYvWuAspI061.jpg',
 ]

def task(url):
    ret = requests.get(url)
    file_name = str(uuid.uuid4()) + '.jpg'
    with open(file_name, mode='wb') as f:
        f.write(ret.content)

for url in url_list:

    t = threading.Thread(target=task,args=(url,))
    t.start()

四、多線程的問題函數

# by luffycity.com
import time
import threading

lock = threading.RLock()

n = 10

def task(i):
    print('這段代碼不加鎖',i)

    lock.acquire() # 加鎖,此區域的代碼同一時刻只能有一個線程執行
    global n
    print('當前線程',i,'讀取到的n值爲:',n)
    n = i
    time.sleep(1)
    print('當前線程',i,'修改n值爲:',n)
    lock.release() # 釋放鎖


for i in range(10):
    t = threading.Thread(target=task,args=(i,))
    t.start()

五、區別ui

Python多線程狀況下:
    - 計算密集型操做:效率低。(GIL鎖)
    - IO操做: 效率高 
                    
Python多進程的狀況下:
    - 計算密集型操做:效率高(浪費資源)。 不得已而爲之。
    - IO操做: 效率高 (浪費資源)。
                
之後寫Python時:
    IO密集型用多線程: 文件/輸入輸出/socket網絡通訊
    計算密集型用多進程。
                
                
擴展:
    Java多線程狀況下:
        - 計算密集型操做:效率高。
        - IO操做: 效率高 
    Python多進程的狀況下:
        - 計算密集型操做:效率高(浪費資源)。
        - IO操做: 效率高 浪費資源)。
                
Python中線程和進程(GIL鎖)
    GIL鎖,全局解釋器鎖。用於限制一個進程中同一時刻只有一個線程被cpu調度。
        
    擴展:默認GIL鎖在執行100個cpu指令(過時時間)。
                    
相關文章
相關標籤/搜索