1. 程式人生 > >day 34 編程之補充內容

day 34 編程之補充內容

完成後 def 們的 守護 add proc lease cer sta

生產消費者模型(必須要理解並且牢記,默寫內容):

技術分享圖片
from multiprocessing import Process,Queue
import time,random,os

def procducer(q):
    for i in range(10):
        res=包子%s %i
        time.sleep(0.5)
        q.put(res)
        print(%s 生產了 %s %(os.getpid(),res))

def consumer(q):
    while True:
        res=q.get()
        
if res is None: break print(%s 吃 %s %(os.getpid(),res)) time.sleep(random.randint(2,3)) if __name__ == __main__: q=Queue() p=Process(target=procducer,args=(q,)) c=Process(target=consumer,args=(q,)) p.start() c.start() p.join() q.put(None)
print()
View Code

今日概要:

1 守護進程vs守護線程(*

2 互斥鎖(**

3 信號量(**

4 生產者消費者模型(*****

5 GIL(什麽時候用進程,什麽時候用線程)(*****) ===========>這裏明天講

守護進程和守護線程:

技術分享圖片
# #守護進程
# from multiprocessing import Process
# import os,time,random
#
# def task():
#     print(‘%s is running‘ %os.getpid())
#     time.sleep(2)
# print(‘%s is done‘ %os.getpid()) # # p = Process(target=time.sleep, args=(3,)) # # p.start() # # if __name__ == ‘__main__‘: # p=Process(target=task) # p.daemon = True #1、必須在p.start()之前 2:守護進程不能開啟子進程 # p.start() # # p.join() # print(‘主‘) # # ‘‘‘ # 舉例說明守護進程的應用場景: # 假設有兩個任務要幹,要玩出並發的效果,使用進程的話可以讓主進程 # 執行一個任務,然後開啟一個子進程執行一個任務。 # # 如果這兩個任務毫無關系,那麽就像上面這麽做就可以 # 如果主進程的任務在執行完畢後,子進程的任務沒有存在的意義了 # 那麽該子進程應該在開啟之前就被設置成守護進程 # ‘‘‘ #迷惑人的例子 #主進程代碼運行完畢,守護進程就會結束 # from multiprocessing import Process # from threading import Thread # import time # def foo(): # print(123) # time.sleep(1) # print("end123") # # def bar(): # print(456) # time.sleep(3) # print("end456") # # if __name__ == ‘__main__‘: # p1=Process(target=foo) # p2 = Process(target=bar) # # p1.daemon=True # p1.start() # p2.start() # print("main-------") #打印該行則主進程代碼結束,則守護進程p1應該被終止,可能會有p1任務執行的打印信息123,因為主進程打印main----時,p1也執行了,但是隨即被終止 # # # #守護線程:等到該進程內所有非守護線程都運行完才死掉 # from multiprocessing import Process # from threading import Thread # import os,time,random # # def task(): # # t=Thread(target=time.sleep,args=(3,)) # # t.start() # print(‘%s is running‘ %os.getpid()) # time.sleep(2) # print(‘%s is done‘ %os.getpid()) # # if __name__ == ‘__main__‘: # t=Thread(target=task) # t.daemon = True #1、必須在t.start()之前 # t.start() # # t.join() # print(‘主‘) #迷惑人的例子 #主進程代碼運行完畢,守護進程就會結束 from multiprocessing import Process from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") if __name__ == __main__: t1=Thread(target=foo) t2 = Thread(target=bar) t1.daemon=True t1.start() t2.start() print("main-------") ‘‘‘ 123 456 main------- end123 end456 ‘‘‘
View Code

理解補充:

這裏的的意思就是:我們要開啟守護進程,開啟的方式要在start之前開啟,然後用固定格式開啟,
# 開啟之後的結果就是,守護進程是等待主進程執行完了自己的代碼之後就會掛掉,至於主進程裏面的其他的子進程就不考慮了,
# 即便那些子進程還沒有執行完成我們也不會去繼續執行了,程序到主進程執行完成後就結束了,這裏就是守護進程的作用.
# 至於他的應用場景,就是在實現並發的情況下,我們在主進程裏面需要開啟其他的進程來幫助我們執行任務,這些任務彼此之間是有關聯的,
# 我們只需要在主進程執行完後就不需要其他的子進程繼續去執行了,
這個時候我們的子進程就需要被設置為守護進程



互斥鎖--------進程:
技術分享圖片
from multiprocessing import Process,Lock
import os,time,random

def task(mutex):
    mutex.acquire()
    print(%s print 1 %os.getpid())
    time.sleep(random.randint(1,3))
    print(%s print 2 %os.getpid())
    time.sleep(random.randint(1, 3))
    print(%s print 3 %os.getpid())
    mutex.release()

if __name__ == __main__:
    # p1=Process(target=task)
    # p2=Process(target=task)
    # p3=Process(target=task)
    # p1.start()
    # p1.join()
    # p2.start()
    # p2.join()
    # p3.start()
    # p3.join()

    mutex=Lock()
    p1=Process(target=task,args=(mutex,))
    p2=Process(target=task,args=(mutex,))
    p3=Process(target=task,args=(mutex,))
    p1.start()
    p2.start()
    p3.start()
View Code

鎖進程的時候,當主進程執行完畢後,守護進程立即掛掉,即便此時還有沒有執行完了子進程也不會去執行了,整個程序立即結束

互斥鎖-------------線程:

技術分享圖片
from threading import Thread,Lock
import time
n=100

def task():
    # global n
    # mutex.acquire()
    # temp=n
    # time.sleep(0.1)
    # n=temp-1
    # mutex.release()

    global n
    with mutex:
        temp=n
        time.sleep(0.1)
        n=temp-1



if __name__ == __main__:
    mutex=Lock()
    t_l=[]
    for i in range(100):
        t=Thread(target=task)
        t_l.append(t)
        t.start()

    for t in t_l:
        t.join()

    print(n)
View Code

線程裏面有兩種情況,如果主線程執行完了此時守護線程還沒有完,就會立即掛掉,但是,如果主線程已經完了,守護線程還沒有完,那麽它作為守護線程也會掛掉.

這裏有一個例子,可以加深對於鎖的理解:

技術分享圖片
from multiprocessing import Process,Lock
import json
import os
import time
import random

# import json
# with open(‘db.txt‘,‘w‘,encoding=‘utf-8‘) as f:
#     json.dump({‘count‘:1},f)
# 在程序運行前先運行一下這上面的三行代碼
def search():
    with open(db.txt,encoding=utf-8) as f:
        dic=json.load(f)
        print(%s 剩余票數 %s %(os.getpid(),dic[count]))

def get():
    with open(db.txt,encoding=utf-8) as read_f:
        dic=json.load(read_f)

    if dic[count] > 0:
        dic[count]-=1
        time.sleep(random.randint(1,3)) #模擬手速+網速
        with open(db.txt,w,encoding=utf-8) as write_f:
            json.dump(dic,write_f)
            print(%s 搶票成功 %os.getpid())

def task(mutex):
    search()
    mutex.acquire()
    get()
    mutex.release()

if __name__ == __main__:
    # for i in range(20):
    #     p=Process(target=task)
    #     p.start()
    #     p.join()

    mutex = Lock()
    for i in range(10):
        p = Process(target=task, args=(mutex, ))
        p.start()
View Code

信號量(理解即可,不必深究):

技術分享圖片
from multiprocessing import Process,Semaphore
# from threading import Thread,Semaphore
import time,random,os

def task(sm):
    with sm:
        print(%s 上廁所 %os.getpid())
        time.sleep(random.randint(1,3))


if __name__ == __main__:
    sm=Semaphore(3)
    for i in range(10):
        p=Process(target=task,args=(sm,))
        p.start()


# 這裏是信號量,它跟進程池就是多了一個鎖的概念,資源搶占,相當於是在一個公司裏有很多# 人要幹活,
# 每個人的分工不同,大家平日裏都是各做各的事情,但是大家都會牽扯到使用打印機的情況,當大家都紮堆使用打印機的時候,
# 這裏就牽扯到了信號量的概念,打印機只有3個,但是使用它的人卻源源不斷理解到這即可
View Code

隊列,堆棧,優先級:

技術分享圖片
from multiprocessing import Queue #進程隊列

# q=Queue(3)
#
# q.put({‘a‘:1})
# q.put(‘xxxxx‘)
# q.put(3)
# q.put(4)


# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get())



import queue #線程隊列

#隊列
# q=queue.Queue(3)
# q.put({‘a‘:1})
# q.put(‘xxxxx‘)
# q.put(3)
# q.put(4)

# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get())

#優先級隊列
# q=queue.PriorityQueue(3)
# q.put((10,{‘a‘:1}))
# q.put((-1,‘xxxxx‘))
# q.put((0,3))
# # q.put(4)
#
# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get())



#堆棧
# q=queue.LifoQueue(3)
# q.put({‘a‘:1})
# q.put(‘xxxxx‘)
# q.put(3)
# # q.put(4)
#
# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get())
View Code

 
# #pip install requests
# import requests
# from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
# from threading import current_thread
# import time
# import os
#
# def get(url):
# print(‘%s GET %s‘ %(os.getpid(),url))
# response=requests.get(url)
# time.sleep(3)
# if response.status_code == 200:
# return {‘url‘:url,‘text‘:response.text}
#
# def parse(obj):
# res=obj.result()
# print(‘[%s] <%s> (%s)‘ % (os.getpid(), res[‘url‘],len(res[‘text‘])))
#
# if __name__ == ‘__main__‘:
# urls = [
# ‘https://www.python.org‘,
# ‘https://www.baidu.com‘,
# ‘https://www.jd.com‘,
# ‘https://www.tmall.com‘,
# ]
# # t=ThreadPoolExecutor(2)
# t=ProcessPoolExecutor(2)
# for url in urls:
# t.submit(get,url).add_done_callback(parse)
# t.shutdown(wait=True)
#
# print(‘‘,os.getpid())

# ‘‘‘
# 異步調用:
# 提交完任務(為該任務綁定一個回調函數),不用再原地等任務執行完畢拿到結果,可以直接提交下一個任務
# 一個任務一旦執行完畢就會自動觸發回調函數的運行
#
# 回調函數的參數是單一的:
# 回調函數的參數就是它所綁定任務的返回值
#
# ‘‘‘


#pip install requests

import requests
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
from threading import current_thread
import time
import os

def get(url):
print(‘%s GET %s‘ %(current_thread().getName(),url))
response=requests.get(url)
time.sleep(3)
if response.status_code == 200:
return {‘url‘:url,‘text‘:response.text}

def parse(obj):
res=obj.result()
print(‘[%s] <%s> (%s)‘ % (current_thread().getName(), res[‘url‘],len(res[‘text‘])))

if __name__ == ‘__main__‘:
urls = [
‘https://www.python.org‘,
‘https://www.baidu.com‘,
‘https://www.jd.com‘,
‘https://www.tmall.com‘,
]
t=ThreadPoolExecutor(2)
for url in urls:
t.submit(get,url).add_done_callback(parse)
t.shutdown(wait=True)

print(,os.getpid())

day 34 編程之補充內容