python--(十步代碼學會線程)

python--(十步代碼學會線程)python

 

 

一.線程的建立安全

 

Thread實例對象的方法
    # isAlive(): 返回線程是否活動的.
    # getname(): 返回線程名.
    # setName(): 設置線程名.

threading模塊提供的一些方法:
   # threading.currentThread(): 返回當前的線程變量。
  # threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啓動後、結束前,不包括啓動前和終止後的線程。
  # threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果

 

from threading import Thread
from multiprocessing import Process

#第一種方法
def func(n):
    print(n)
if __name__ == '__main__':

    t = Thread(target=func, args=("我是線程",))
    t.start()
    # p = Process(target=func, args=("我是進程",))
    # p.start()
    print("主進程結束.")

#第二種方法
class MyThread(Thread):
    def run(self):
        print("輝哥牛逼")
if __name__ == "__main__":
    t = MyThread()
    t.start()
    print("主線程結束")
線程的兩種建立方式

 

import time
from threading import Thread
from multiprocessing import Process
def func(n):
    num = 0
    for n1 in range(n):
        num += n1
    print("num",num)
if __name__ == '__main__':
    t_s_t = time.time()
    t_list = []
    for i in range(10):
        t = Thread(target=func, args=(10,))
        t.start()       #速度特別快
        t_list.append(t)
    [tt.join() for tt in t_list]
    t_e_t = time.time()
    t_dif_t = t_s_t - t_e_t     #獲取了線程的執行時間

    p_s_t = time.time()
    p_list = []
    for ii in range(10):
        p = Process(target=func, args=(10,))
        p.start()   #速度很是快
        p_list.append(p)
    [pp.join() for pp in p_list]
    p_e_t = time.time() #結束時間
    p_dif_t = p_e_t - p_s_t #獲取進程執行時間

    print('線程>>>>', t_dif_t)
    print('進程....', p_dif_t)
    print('主線程結束')
線程和進程的效率對比

線程的其餘方法app

# 線程的一些其餘方法
# from threading import Thread
# import threading
# import time
# from multiprocessing import Process
# import os
#
# def work():
#     import time
#     time.sleep(1)
#     print(threading.current_thread().getName()) #Thread-1
#     print(threading.current_thread())   #Thtrad-1
#
# if __name__ == '__main__':
#     #在主進程下開啓線程
#     t = Thread(target=work)
#     t.start()
#
#     # print(threading.current_thread()) #主線程對象
#     # print(threading.current_thread().getName()) #主線程名稱
#     # print(threading.current_thread().ident) #主線程ID
#     # print(threading.get_ident()) #主線程ID
#
#     time.sleep(3)
#     print(threading.enumerate()) #連同主線程在內有兩個運行的線程
#     print(threading.active_count()) #進程數
#     print("主線程/主進程")
View Code

 


二.數據共享異步

from threading import Thread
from multiprocessing import Process

num = 100
def func():
    global num
    num = 0
if __name__ == '__main__':
    t = Thread(target=func,)
    t.start()
    t.join()
    print(num)

    # p = Process(target=func,)
    # p.start()
    # p.join()
    # print(num)
線程的數據是共享的
mport time
from threading import Thread,Lock

#演示共享資源的時候,數據不安全的問題
# num = 100
# def func():
#     global num
#     num -= 1
#     mid = num
#     mid = mid - 1
#     time.sleep(0.00001)
#     num = mid
# if __name__ == '__main__':
#     t_list = []
#     for i in range(10):
#         t = Thread(target=func,)
#         t.start()
#         t_list.append(t)
#     [tt.join() for tt in t_list]
#     print("主進程>>>>", num)

#經過鎖來解決數據不安全的問題,線程模塊裏面引入的鎖
num = 100
def func(t_lock):
    global num
    t_lock.acquire()
    mid = num
    mid = mid - 1
    time.sleep(0.0001)
    num = mid
    t_lock.release()
if __name__ == '__main__':
    t_lock = Lock() #鎖對象(同步鎖,互斥鎖)
    t_list = []
    for i in range(10):
        t = Thread(target=func,args=(t_lock,))
        t.start()
        t_list.append(t)
    [tt.join() for tt in t_list]
    print("主進程>>>>",num)
線程共享資源不安全,加鎖解決

 

三.守護進程ide

守護進程 :函數

主進程代碼結束程序並無結束,而且主進程還存在,進程等待其餘的子進程執行結束之後,爲子進程收屍,注意一個問題:主進程的代碼運行結束守護進程跟着結束,ui

守護線程:spa

主線程等待全部非守護線程的結束才結束,主線程的代碼運行結束,還要等待非守護線程的執行完畢.這個過程當中守護線程還存在線程

 1 import time
 2 from threading  import Thread
 3 from multiprocessing import Process
 4 def func1(n):
 5     time.sleep(5)
 6     print(n)
 7 def func2(n):
 8     time.sleep(3)
 9     print(n)
10 if __name__ == '__main__':
11     # p1 = Process(target=func1,args=("我是子進程1號",))
12     #     #設置守護進程,在start以前加
13     # p1.start()
14     # p2 = Process(target=func2,args=("我是子進程2號",))
15     # p2.daemon = True
16     # p2.start()
17     # print("子進程結束")
線程與進程守護進程對比

 

四.死鎖現象3d

 

鎖(同步鎖\互斥鎖):  保證數據安全,可是犧牲了效率,同步執行鎖內的代碼

死鎖現象 :   互相搶到了對方的須要的鎖,致使雙方相互等待,程序無法進行

解決死鎖:  遞歸鎖,RLock   #能夠屢次acquire,經過一個計數器來記錄被鎖了多少次,只有計數器爲0的時候,大 家才能繼續搶鎖

import time
from threading import Thread,Lock

class MyThread(Thread):

    def __init__(self,lockA,lockB):
        super().__init__()
        self.lockA = lockA
        self.lockB = lockB

    def run(self):
        self.f1()
        self.f2()
    def f1(self):

        self.lockA.acquire()
        print('我拿了A鎖')

        self.lockB.acquire()
        print('我是一個很好的客戶!')
        self.lockB.release()

        self.lockA.release()

    def f2(self):
        self.lockB.acquire()
        time.sleep(0.1)
        print('我拿到了B鎖')
        self.lockA.acquire()
        print('我是一名合格的技師')
        self.lockA.release()

        self.lockB.release()


if __name__ == '__main__':
    lockA = Lock()
    lockB = Lock()

    t1 = MyThread(lockA,lockB)
    t1.start()

    t2 = MyThread(lockA,lockB)
    t2.start()

    print('我是經理')
死鎖現象
import time
from threading import Thread,Lock,RLock  #遞歸鎖

class MyThread(Thread):

    def __init__(self,lockA,lockB):
        super().__init__()
        self.lockA = lockA
        self.lockB = lockB

    def run(self):
        self.f1()
        self.f2()
    def f1(self):

        self.lockA.acquire()
        print('我拿了A鎖')

        self.lockB.acquire()
        print('我是一個很好的客戶!')
        self.lockB.release()

        self.lockA.release()

    def f2(self):
        self.lockB.acquire()
        time.sleep(0.1)
        print('我拿到了B鎖')
        self.lockA.acquire()
        print('我是一名合格的技師')
        self.lockA.release()

        self.lockB.release()


if __name__ == '__main__':
    # lockA = Lock()
    # lockB = Lock()
    # lockA = lockB = Lock() #不要這麼寫,別本身玩本身,鎖本身
    lockA = lockB = RLock()

    t1 = MyThread(lockA,lockB)
    t1.start()

    t2 = MyThread(lockA,lockB)
    t2.start()

    print('我是經理')
解決死鎖線程方法

 

五.信號量

信號量:  控制同時可以進入鎖內去執行代碼的線程數量(進程數量),維護了一個計數器,剛開始建立信號量的時候假如設置的是4個房間,進入一次acquire就減1 ,出來一個就+1,若是計數器爲0,那麼其餘的任務等待,這樣其餘的任務和正在執行的任務是一個同步的狀態,而進入acquire裏面去執行的那4個任務是異步執行的.

 

import time
from threading import Thread, Semaphore

def func1(s):
    s.acquire()
    time.sleep(1)
    print('大寶劍!!!')
    s.release()

if __name__ == '__main__':
    s = Semaphore(4)
    for i in range(10):
        t = Thread(target=func1,args=(s,))
        t.start()
信號量

 

六.事件

# # 事件
# from threading import Thread,Event
# e = Event() #e的狀態有兩種,False Ture,當事件對象的狀態爲False的時候,wait的位置會阻塞
#
# e.set() #將事件對象的狀態改成Ture
# e.clear() #將事件對象的狀態改成False
# print("在這裏等待")
# e.wait() #阻塞
# print("還沒好")
View Code

 

七.隊列

mport queue

#先進先出 FIFO
# q=queue.Queue()
# q.put('first')
# q.put('second')
# q.put('third')
# # q.put_nowait() #沒有數據就報錯,能夠經過try來搞
# print(q.get())
# print(q.get())
# print(q.get())
# # q.get_nowait() #沒有數據就報錯,能夠經過try來搞

# '''
# first
# second
# third
# '''

# 先進後出
# import queue

# q = queue.LifoQueue() #隊列相似於棧,先進後出的順序
# q.put('first')
# q.put('second')
# q.put('third')
# q.put_nowait()

# print(q.get())
# print(q.get())
# print(q.get())
# # q.get_nowait()    #沒有數據就報錯

# '''
# third
# second
# first
# '''


# # 優先級隊列
# import queue
# q = queue.PriorityQueue()
# #put進入一個元祖,元祖的第一個元素是優先級(一般是數字,也能夠是非數字之間的比較,數字越小優先級越高
# q.put((-10,"a"))
# q.put((-5,"a")) #負數也能夠
#
# # q.put((20,'b')) #若是第一個參數數字的優先級同樣,那麼按照後面的字符串acsii來排序
# # q.put((20,'c'))
#
# # q.put((20,{'a':11})) #TypeError: unorderable types: dict() < dict() 不能是字典
# # q.put((20,('w',1)))  #優先級相同的兩個數據,他們後面的值必須是相同的數據類型才能比較,能夠是元祖,也是經過元素的ascii碼順序來排序
#
# print(q.get())
# print(q.get())
# """結果:數字越小優先級越高,優先級高的優先出隊"""
View Code

 

八.線程池

 

concurrent.futures模塊提供了高度封裝的異步調用接口
ThreadPoolExecutor:線程池,提供異步調用
ProcessPoolExecutor: 進程池,提供異步調用
Both implement the same interface, which is defined by the abstract Executor class.

#2 基本方法
#submit(fn, *args, **kwargs)
異步提交任務

#map(func, *iterables, timeout=None, chunksize=1) 
取代for循環submit的操做

#shutdown(wait=True) 
至關於進程池的pool.close()+pool.join()操做
wait=True,等待池內全部任務執行完畢回收完資源後才繼續
wait=False,當即返回,並不會等待池內的任務執行完畢
但無論wait參數爲什麼值,整個程序都會等到全部任務執行完畢
submit和map必須在shutdown以前

#result(timeout=None)
取得結果

#add_done_callback(fn)
回調函數

 

# 線程池
# import time
# from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
# #ProcessPoolExecutor 進程池
# from threading import current_thread
#
# def func(n):
#     time.sleep(1)
#     # print(n,current_thread().ident)
#     return n**2
# if __name__ == '__main__':
#     t_p = ThreadPoolExecutor(max_workers = 4)
#     map_res = t_p.map(func,range(10))   #異步執行的,map自帶join功能
#     print(map_res)
#     print([i for i in map_res])
View Code

線程池的一些其餘方法

# 線程池的一些其餘方法
# import time
# from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
# from threading import current_thread
# def func(n):
#     time.sleep(1)
#     #print(n,current_thread().ident)
#     return n**2
# def func2(n):
#     print(n)
# if __name__ == '__main__':
#     t_p = ThreadPoolExecutor(max_workers=4)
#     t_p_list = []
#     for i in range(10):
#         res_obj = t_p.submit(func, i) #異步提交了這10個任務
#         # res_obj.result()    #他和get同樣
#         t_p_list.append(res_obj)
#     t_p.shutdown()  #close + join 等待所有完成以後關閉子線程,防止後面數據進入
#     # print('t_res_list',t_p_list)
#     for e_res in t_p_list:
#         print(e_res.result())
View Code

 

九.回調函數

rom concurrent.futures import ThreadPoolExecutor
from threading import current_thread

def func(n):
    time.sleep(1)
    print(n**2)
    # print(n,current_thread().getName())
    # return n**2
def func2(n):
    # print("current_thread>>>>",current_thread().getName())
    print(n.result())  #result() 至關於 get()
if __name__ == '__main__':
    t_p = ThreadPoolExecutor(max_workers=1)
    for i in range(3):
        t_p.submit(func, i).add_done_callback(func2)

    print('主進程結束')
View Code

 

十.GIL鎖

#保證數據安全,鎖的是整個線程,每次只能有一個線程使用cpu,是CPython解釋器的特性
     

相關文章
相關標籤/搜索