1)第一代計算機(1940~1955)python
一、第二代計算機(1955~1965):晶體管和批處理系統程序員
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/18/2018 4:14 PM "" """ 開啓子進程的兩種方式 """ #開啓進程的方式1: from multiprocessing import Process import time def task(name): """ 任務函數 :param name: :return: """ print('%s is running'%name) time.sleep(3) print('%s is done'%name) if __name__ == '__main__': #Process(target= task, kwargs={'name':'子進程1'}) p = Process(target = task, args = ('子進程1',)) p.start()#僅僅只是給操做系統發送了一個信號; print('主') """ 主 子進程1 is running 子進程1 is done """ """ 開啓進程的方式2: """ from multiprocessing import Process import time class MyProcess(Process): def __init__(self,name): super().__init__() self.name = name def run(self):#默認必須叫作run print('%s in running'%self.name) time.sleep(3) print('%s is done'%self.name) if __name__ == '__main__': p = MyProcess('子進程1') p.start() print('主') """ 主 子進程1 in running 子進程1 is done """
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/18/2018 4:52 PM "" """ 10-查看進程的pid與ppid 操做系統管理進行,使用pid號,相似人類的身份證號; """ from multiprocessing import Process import time import os def task(): print('%s is running,partent id is <%s>'%(os.getpid(),os.getppid())) time.sleep(3) print('%s is done,partent id is <%s>'%(os.getpid(),os.getppid())) if __name__ == '__main__': #p = Process(target= task, args=('子進程1'))#TypeError: task() takes 0 positional arguments but 4 were given p = Process(target= task,) p.start() print('主%s,partent id is <%s>'%(os.getpid(),os.getppid())) """ 主 12040 16924 is running 16924 is done ---------------------- 主888,partent id is <14600> 19400 is running,partent id is <888> 19400 is done,partent id is <888> ----------------------------------- C:\\Users\\TQTL911>tasklist |findstr pycharm pycharm64.exe 14600 Console 6 823,488 K C:\\Users\\TQTL911> """
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/18/2018 5:07 PM "" """ 11-殭屍進程與孤兒進程; 此內容瞭解爲主; 一、殭屍進程,即子進程被殺死後的狀態,方便於父進程查看一些狀態信息,但他是有害的; 二、孤兒進程,即父進程終止後,保存的子進程,但會交由祖宗進程init(全部進程的起點,即孤兒院)去進行管理,它是無害的; """
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/18/2018 5:17 PM "" """ 12-Process對象的其餘屬性或方法 """ #一、join方法講解 from multiprocessing import Process import time import os import random def task(): print('%s is running,The parent id is <%s>'%(os.getpid(),os.getppid())) time.sleep(random.randrange(1,5)) print('%s is down,The parent id is <%s>'%(os.getpid(),os.getppid())) if __name__ == '__main__': p = Process(target=task,) p.start() p.join()#保證等待子進程執行結束,父進程才執行 print('主',os.getpid(),os.getppid()) print(p.pid) #二、引入join方法 from multiprocessing import Process import time import os import random def task(name): print('%s is running'%name) time.sleep(random.randrange(1,3)) if __name__ == '__main__': p1 = Process(target=task,args=('子進程1',)) p2 = Process(target=task,args=('子進程2',)) p3 = Process(target=task,args=('子進程3',)) p4 = Process(target=task,args=('子進程4',)) p1.start()#只是發個信號給操做系統,至於CPU執行的順序,由操做系統來分配; p2.start() p3.start() p4.start() p1.join()#保證等待子進程執行結束,父進程才執行 p2.join()#保證等待子進程執行結束,父進程才執行 p3.join()#保證等待子進程執行結束,父進程才執行 p4.join()#保證等待子進程執行結束,父進程才執行 print('主',os.getpid(),os.getppid()) """ 一、不曾使用join方法的時候,執行的順序以下所示: 主 14188 14600 子進程1 is running 子進程3 is running 子進程2 is running 子進程4 is running 二、使用了join方法以後,執行的順序以下所示: 子進程1 is running 子進程2 is running 子進程3 is running 子進程4 is running 主 2564 14600 """ #三、並行執行程序; from multiprocessing import Process import os import random import time def task(name,n): print('%s is runing'%name,10) time.sleep(n) if __name__ == '__main__': start = time.time() p1 = Process(target= task, args=('子進程1',5)) p2 = Process(target= task, args=('子進程2',3)) p3 = Process(target= task, args=('子進程3',2)) p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() print('主',(time.time() - start)) """ 子進程1 is runing 10 子進程3 is runing 10 子進程2 is runing 10 主 5.093375205993652 """ #四、變成串行方式執行程序; from multiprocessing import Process import os import time def task(name,n): print('%s is running'%name,n) time.sleep(n) if __name__ == '__main__': start = time.time() # p1 = Process(target= task,args=('子進程1',5),) # p2 = Process(target= task,args=('子進程2',1),) # p3 = Process(target= task,args=('子進程3',2),) # # p1.start() # p1.join() # p2.start() # p2.join() # p3.start() # p3.join() #對以上內容的簡寫 p1 = Process(target=task, args=('子進程1', 5), ) p2 = Process(target=task, args=('子進程2', 1), ) p3 = Process(target=task, args=('子進程3', 2), ) p_l = [p1,p2,p3] for p in p_l: p.start() for p in p_l: #p.join()#TabError: inconsistent use of tabs and spaces in indentation p.join() #print('主',time.time() - start)#NameError: name 'start' is not defined print('主',time.time() - start) """ 子進程1 is running 5 子進程2 is running 1 子進程3 is running 2 主 8.224236726760864 """ #小結 from multiprocessing import Process import os import time import random def task(): print('%s is runing,The parent id is <%s>'%(os.getpid(),os.getppid())) time.sleep(random.randrange(1,3)) print('%s is done,The parent id is <%s>'%(os.getpid(),os.getppid())) if __name__ == '__main__':#儘量手寫,不使用main自動生成,會出現tab != 4個空格的坑呀! # p = Process(target= task,) # p.start() # p.join() # print('主',os.getpid(),os.getppid()) # print(p.pid) # print(p.is_alive())#布爾值False or True p = Process(target=task,) p.start() p.terminate() time.sleep(3)#加上時間後,is_alive將會變成False print(p.is_alive())#True print('主',os.getpid(),os.getppid())
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/18/2018 6:53 PM from multiprocessing import Process import time import random def task(n): time.sleep(random.randrange(1,3)) print('--------->%s'%n) if __name__ == '__main__': p1 = Process(target=task,args=(1,)) p2 = Process(target=task,args=(2,)) p3 = Process(target=task,args=(3,)) # Req1:最早保證輸出--------->4 p1.start() p2.start() p3.start() print('最早保證輸出--------->4') #Req2:保證最後輸出--------->4 p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() print('保證最後輸出--------->4') #Req3:保證按順序輸出--------->4 #以下寫,變成串行,失去併發的意義,沒有意義,爲了練習join方法的使用; p1.start() p1.join() p2.start() p1.join() p3.start() p1.join() print('保證按順序輸出--------->4')
1)server端;數據庫
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/18/2018 6:37 PM from socket import * from multiprocessing import Process def talk(conn): while True: try: data = conn.recv(1024) if not data:break conn.send(data.upper()) except ConnectionResetError: break conn.close() def server(ip,port): server = socket(AF_INET,SOCK_STREAM) server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) server.bind((ip,port))#注意此處爲元組形式的ip_port:(ip,port) server.listen(5) while True: conn,addr = server.accept() p = Process(target=talk,args=(conn,)) p.start() server.close() if __name__ == '__main__': server('127.0.0.1',9011)
2)client端;編程
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/18/2018 6:37 PM from socket import * client = socket(AF_INET,SOCK_STREAM) client.connect(('127.0.0.1',9011)) while True: msg = input('>>>:').strip() if not msg:continue client.send(msg.encode('utf-8')) data = client.recv(1024) print(data.decode('utf-8'))
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 8:26 AM "" """ 守護進程-伴隨着父進程而消失; """ from multiprocessing import Process import time import random def task(name): print('%s is running'%name) time.sleep(random.randrange(1,3)) # p = Process(target=time.sleep,args=(3,)) # p.start()#AssertionError: daemonic processes are not allowed to have children if __name__ == '__main__': p = Process(target=task,args=('子進程1',)) p.daemon = True p.start() p.join() print('主進程') #練習題; from multiprocessing import Process 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#必定要在p.start()前設置,設置p爲守護進程,禁止p建立子進程,而且父進程代碼執行結束,p即終止運行 p1.start() p2.start() print("main-------") """ main-------#只要碰到main,就不會出現123和end123; 456 end456 """
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 8:44 AM "" """ 互斥鎖-互相排斥,好比生活中去衛生間,關上門,其餘人必須等待; 互斥鎖的原理-把併發改爲串行,下降了效率,可是保證了數據安全不錯亂; """ from multiprocessing import Process,Lock import time import random """ 進程之間數據不共享,可是共享同一套文件系統,因此訪問同一個文件, 或同一個打印終端,是沒有問題的,而共享帶來的是競爭, 競爭帶來的結果就是錯亂,以下: """ def task(name,mutex):#mutex互斥的意思; mutex.acquire()#獲取鎖; print('%s 1'%name) time.sleep(random.randrange(1,2)) print('%s 2'%name) time.sleep(random.randrange(1,2)) print('%s 3'%name) mutex.release()#釋放鎖; if __name__ == '__main__': mutex = Lock()#生成鎖 for i in range(3): p = Process(target=task,args=('進程%s'%i,mutex)) p.start() """ 一、未引入互斥鎖 進程0 1 進程1 1 進程2 1 進程0 2 進程1 2 進程2 2 進程0 3 進程1 3 進程2 3 二、引入互斥鎖 進程0 1 進程0 2 進程0 3 進程1 1 進程1 2 進程1 3 進程2 1 進程2 2 進程2 3 """
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 8:55 AM "" """ 16-模擬搶票 """ from multiprocessing import Process,Lock import time import random import json def search(name): time.sleep(random.randrange(1,2)) dic = json.load(open('db.txt','r',encoding='utf-8')) print('<%s> 查看到剩餘票數[%s]'%(name,dic['count'])) def get(name): time.sleep(random.randrange(1,2))#模擬讀取數據的網絡延遲: dic = json.load(open('db.txt','r',encoding = 'utf-8')) if dic['count'] > 0: dic['count'] -= 1 time.sleep(2) json.dump(dic,open('db.txt','w',encoding='utf-8')) print('<%s>購票成功'%name) def task(name): search(name) get(name) if __name__ == '__main__': for i in range(10): p = Process(target = task,args=('路人%s'%i,)) p.start() """ <路人0> 查看到剩餘票數[1] <路人1> 查看到剩餘票數[1] <路人2> 查看到剩餘票數[1] <路人4> 查看到剩餘票數[1] <路人3> 查看到剩餘票數[1] <路人6> 查看到剩餘票數[1] <路人5> 查看到剩餘票數[1] <路人7> 查看到剩餘票數[1] <路人8> 查看到剩餘票數[1] <路人9> 查看到剩餘票數[1] <路人0>購票成功 <路人1>購票成功 <路人2>購票成功 <路人4>購票成功 <路人3>購票成功 <路人6>購票成功 <路人5>購票成功 <路人7>購票成功 <路人8>購票成功 <路人9>購票成功 """ #加鎖處理:購票行爲由併發變成了串行,犧牲了運行效率,但保證了數據安全 from multiprocessing import Process,Lock import time import random import json def search(name): time.sleep(random.randrange(1,2)) dic = json.load(open('db.txt','r',encoding='utf-8')) print('<%s> 查看到剩餘票數[%s]'%(name,dic['count'])) def get(name): time.sleep(random.randrange(1,2))#模擬讀取數據的網絡延遲: dic = json.load(open('db.txt','r',encoding = 'utf-8')) if dic['count'] > 0: dic['count'] -= 1 time.sleep(2) json.dump(dic,open('db.txt','w',encoding='utf-8')) print('<%s>購票成功'%name) def task(name,mutex): #mutex.acquire()#此處,注意加鎖的順序; search(name) mutex.acquire() get(name) mutex.release() """ <路人0> 查看到剩餘票數[1] <路人0>購票成功 <路人1> 查看到剩餘票數[0] <路人2> 查看到剩餘票數[0] <路人3> 查看到剩餘票數[0] <路人4> 查看到剩餘票數[0] <路人5> 查看到剩餘票數[0] <路人8> 查看到剩餘票數[0] <路人7> 查看到剩餘票數[0] <路人6> 查看到剩餘票數[0] <路人9> 查看到剩餘票數[0] """ if __name__ == '__main__': mutex = Lock() for i in range(10): p = Process(target = task,args=('路人%s'%i,mutex)) p.start() """ <路人2> 查看到剩餘票數[1] <路人0> 查看到剩餘票數[1] <路人3> 查看到剩餘票數[1] <路人7> 查看到剩餘票數[1] <路人1> 查看到剩餘票數[1] <路人6> 查看到剩餘票數[1] <路人5> 查看到剩餘票數[1] <路人8> 查看到剩餘票數[1] <路人9> 查看到剩餘票數[1] <路人4> 查看到剩餘票數[1] <路人2>購票成功 """
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 9:49 AM from multiprocessing import Process,Lock import time import random import json def search(name): time.sleep(random.randrange(1,2)) dic = json.load(open('db.txt','r',encoding='utf-8')) print('<%s> 查看到剩餘票數[%s]'%(name,dic['count'])) def get(name): time.sleep(random.randrange(1,2))#模擬讀取數據的網絡延遲: dic = json.load(open('db.txt','r',encoding = 'utf-8')) if dic['count'] > 0: dic['count'] -= 1 time.sleep(2) json.dump(dic,open('db.txt','w',encoding='utf-8')) print('<%s>購票成功'%name) else: print('<%s>購票失敗'%name) def task(name,): #mutex.acquire() search(name) #mutex.acquire() get(name) #mutex.release() if __name__ == '__main__': #mutex = Lock() for i in range(10): p = Process(target = task,args=('路人%s'%i,))#args傳值爲元組,帶有逗號 p.start() p.join() """ <路人0> 查看到剩餘票數[1] <路人0>購票成功 <路人1> 查看到剩餘票數[0] <路人1>購票失敗 <路人2> 查看到剩餘票數[0] <路人2>購票失敗 <路人3> 查看到剩餘票數[0] <路人3>購票失敗 <路人4> 查看到剩餘票數[0] <路人4>購票失敗 <路人5> 查看到剩餘票數[0] <路人5>購票失敗 <路人6> 查看到剩餘票數[0] <路人6>購票失敗 <路人7> 查看到剩餘票數[0] <路人7>購票失敗 <路人8> 查看到剩餘票數[0] <路人8>購票失敗 <路人9> 查看到剩餘票數[0] <路人9>購票失敗 """ #小結: """ 一、發現使用join方法後,將併發改成串行,確實能保證數據安全,但問題連查票操做也 變成只能一個一個去查了,很明顯,你們查票的時候應該是併發地去查詢 而無需考慮數據正確與否,此時join與互斥鎖的區別就顯而易見了。 二、join是將一個任務總體串行,而互斥鎖的好處則是將一個任務中的某一行代碼串行,好比只讓 task函數的get任務串行; def task(name,): search(name)#併發執行 Lock.acquire() get(name)#串行執行 Lock.release() """
進程彼此之間互相隔離,要實現進程間通訊(IPC),multiprocessing模塊支持兩種形式:隊列和管道,這兩種方式都是使用消息傳遞的;json
1)建立隊列的類(底層就是以管道和鎖定的方式實現的)緩存
Queue([maxsize]):建立共享的進程隊列,Queue是多進程安全的隊列,可使用Queue實現多進程之間的數據傳遞。
2)Queue的參數介紹;安全
maxsize是隊列中容許最大項數,省略則無大小限制。 但須要明確: 一、隊列內存放的是消息而非大數據 二、隊列佔用的是內存空間,於是maxsize即使是無大小限制也受限於內存大小
3)主要方法介紹網絡
q = Queue(n) q.put方法用以插入數據到隊列中。 q.get方法能夠從隊列讀取而且刪除一個元素。
4)隊列的使用多線程
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 10:04 AM "" """ 掌握隊列的使用-先進先出的原則 """ from multiprocessing import Queue q = Queue(3)#設置隊列數爲3,注意:隊列中不能放置大文件,而應該是精簡的消息; q.put('hello') q.put({'a':1}) q.put([1,2,3,4]) #q.put(4) print(q.get()) print(q.get()) print(q.get()) print(q.empty())#清空隊列操做;返回值爲True; #print(q.get())#當隊列中的數據被取空以後,再次get,程序將一直停留在這裏;
生產者指的是生產數據的任務,消費者指的是處理數據的任務,在併發編程中,若是生產者處理速度很快,而消費者處理速度很慢,那麼生產者就必須等待消費者處理完,才能繼續生產數據。一樣的道理,若是消費者的處理能力大於生產者,那麼消費者就必須等待生產者。爲了解決這個問題因而引入了生產者和消費者模式。
生產者和消費者彼此之間不直接通信,而經過阻塞隊列來進行通信,因此生產者生產完數據以後不用等待消費者處理,直接扔給阻塞隊列,消費者不找生產者要數據,而是直接從阻塞隊列裏取,阻塞隊列就至關於一個緩衝區,平衡了生產者和消費者的處理能力。 注意:這個阻塞隊列就是用來給生產者和消費者解耦的
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 10:11 AM "" """ 19-生產者消費者模型 """ import time def producter(): for i in range(3): res = '包子%s'%i print('生產者生產了%s'%res) consumer(res) def consumer(res): time.sleep(1) print('消費者吃了%s'%res) producter() """ 生產者生產了包子0 消費者吃了包子0 生產者生產了包子1 消費者吃了包子1 生產者生產了包子2 消費者吃了包子2 """ """ #生產者與消費者之間彼此可能等待對方; #引入生產者消費者模型,在生產者與消費者之間引入一個「容器」,相似於緩存的做用; #好處之一:解耦合; #好處之二平衡了消費者和生產者之間的不對等的能力: """ from multiprocessing import Process,Queue import time def producter(q): for i in range(10): res = '包子%s'%i time.sleep(0.5)#模擬生產消耗的時間 print('生產者生產了%s'%res) q.put(res) def consumer(q): while True: res = q.get() time.sleep(1) print('消費者吃了%s'%res) if __name__ == '__main__': #中間的容器 q = Queue() #生產者 p1 = Process(target=producter,args=(q,)) #消費者們 c1 = Process(target=consumer,args=(q,)) p1.start() c1.start() print('主') """ 主 生產者生產了包子0 生產者生產了包子1 生產者生產了包子2 消費者吃了包子0 生產者生產了包子3 消費者吃了包子1 生產者生產了包子4 生產者生產了包子5 消費者吃了包子2 生產者生產了包子6 生產者生產了包子7 消費者吃了包子3 生產者生產了包子8 生產者生產了包子9 消費者吃了包子4 消費者吃了包子5 消費者吃了包子6 消費者吃了包子7 消費者吃了包子8 消費者吃了包子9 引入了隊列的概念,生產者與消費者之間互不影響;但以上會出現消費者持續等待的情景 """ """ 生產者生產了包子0 生產者生產了包子1 消費者吃了包子0 生產者生產了包子2 生產者生產了包子3 生產者生產了包子4 消費者吃了包子1 生產者生產了包子5 消費者吃了包子2 生產者生產了包子6 生產者生產了包子7 消費者吃了包子3 生產者生產了包子8 生產者生產了包子9 主 消費者吃了包子4 消費者吃了包子5 消費者吃了包子6 消費者吃了包子7 消費者吃了包子8 消費者吃了包子9 Process finished with exit code 0 """ #生產者有多個; from multiprocessing import Process,Queue import time def producter(q): for i in range(10): res = '包子%s'%i time.sleep(0.5)#模擬生產消耗的時間 print('生產者生產了%s'%res) q.put(res) def consumer(q): while True: res = q.get() if res is None:break time.sleep(1) print('消費者吃了%s'%res) if __name__ == '__main__': #中間的容器 q = Queue() #生產者 p1 = Process(target=producter,args=(q,)) p2 = Process(target=producter,args=(q,)) p3 = Process(target=producter,args=(q,)) p4 = Process(target=producter,args=(q,)) #消費者們 c1 = Process(target=consumer,args=(q,)) c2 = Process(target=consumer,args=(q,)) c3 = Process(target=consumer,args=(q,)) p1.start() p2.start() p3.start() p4.start() c1.start() c2.start() c3.start() p1.join() p2.join() p3.join() p4.join() q.put(None) q.put(None) q.put(None) print('主')
這就像是一個Queue對象,但隊列容許項目的使用者通知生成者項目已經被成功處理。通知進程是使用共享的信號和條件變量來實現的。
JoinableQueue的實例p除了與Queue對象相同的方法以外還具備: q.task_done():使用者使用此方法發出信號,表示q.get()的返回項目已經被處理。若是調用此方法的次數大於從隊列中刪除項目的數量,將引起ValueError異常 q.join():生產者調用此方法進行阻塞,直到隊列中全部的項目均被處理。阻塞將持續到隊列中的每一個項目均調用q.task_done()方法爲止
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 11:24 AM from multiprocessing import Process,JoinableQueue,Queue import time import random def producer(q): for i in range(3): res = '包子%s'%i time.sleep(0.5) print('生產了%s'%res) q.put(res) q.join() def consumer(q): while True: res = q.get() if res is None:break time.sleep(1) print('消費者吃了%s'%res) q.task_done() if __name__ == '__main__': #容器 q = JoinableQueue() p1 = Process(target=producer,args=(q,)) p2 = Process(target=producer,args=(q,)) p3 = Process(target=producer,args=(q,)) c1 = Process(target=consumer,args=(q,)) c2 = Process(target=consumer,args=(q,)) c1.daemon = True c2.daemon = True p1.start() p2.start() p3.start() c1.start() c2.start() p1.join() p2.join() p3.join() print('主') """ 生產了包子0 生產了包子0 生產了包子0 生產了包子1 生產了包子1 生產了包子1 消費者吃了包子0 生產了包子2 消費者吃了包子0 生產了包子2 生產了包子2 消費者吃了包子0 消費者吃了包子1 消費者吃了包子1 消費者吃了包子1 消費者吃了包子2 消費者吃了包子2 消費者吃了包子2 主 Process finished with exit code 0 """
在傳統操做系統中,每一個進程有一個地址空間,並且默認就有一個控制線程 線程顧名思義,就是一條流水線工做的過程(流水線的工做須要電源,電源就至關於cpu),而一條流水線必須屬於一個車間,一個車間的工做過程是一個進程,車間負責把資源整合到一塊兒,是一個資源單位,而一個車間內至少有一條流水線。
多線程(即多個控制線程)的概念是,在一個進程中存在多個線程,多個線程共享該進程的地址空間,至關於一個車間內有多條流水線,都共用一個車間的資源。例如,北京地鐵與上海地鐵是不一樣的進程,而北京地鐵裏的13號線是一個線程,北京地鐵全部的線路共享北京地鐵全部的資源,好比全部的乘客能夠被全部線路拉。
1) 來點兒英文範兒吧!併發
一、Threads share the address space of the process that created it; processes have their own address space. 二、Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process. 三、Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes. 四、New threads are easily created; new processes require duplication of the parent process. 五、Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes. 五、Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.
2)算了,仍是別裝13了,直接上中文吧!
一、開啓一個字處理軟件進程,該進程確定須要辦不止一件事情,好比監聽鍵盤輸入,處理文字,定時自動將文字保存到硬盤,這三個任務操做的都是同一塊數據,於是不能用多進程。
二、只能在一個進程裏併發地開啓三個線程,若是是單線程,那就只能是,鍵盤輸入時,不能處理文字和自動保存,自動保存時又不能輸入和處理文字。
threading與multiprocessing模塊很是類似,具體見後者的用法章節;
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 11:53 AM "" """ 22-開啓線程的兩種方式 """ #回顧開進程的方式; import time import random from multiprocessing import Process def piao(name): print('%s piaoing'%name) time.sleep(random.randrange(1,3)) print('%s piao ended'%name) if __name__ == '__main__': p1 = Process(target=piao,args=('cuixiaozhao',))#必須加上,號 #調用對象下的方法,開啓四個進程 p1.start() print('主') #開啓線程的方式1: import time import random from threading import Thread def piao(name): print('%s piaoing'%name) time.sleep(random.randrange(1,3)) print('%s piao ended'%name) if __name__ == '__main__': t1 = Thread(target=piao,args=('cuixiaozhao',))#必須加上,號 t1.start() print('主線程1') #開啓線程的方式2 from threading import Thread import time class MyThread(Thread): def __init__(self,name): super().__init__() self.name = name def run(self):#默認必須叫作run print('%s in running'%self.name) time.sleep(3) print('%s is done'%self.name) if __name__ == '__main__': t = MyThread('子線程2') t.start() print('主線程2') """ 小結: 一、起線程的兩種方式與起進程的兩種很是很是類似,幾乎如出一轍,就是把multiprocessing換成threading便可 二、明確清楚進程與線程的概念區別: 同一個進程內的多線線程共享該進程內的地址資源 建立線程的開銷要遠小於建立進程的開銷(建立一個進程,就是建立一個車間,設計到申請空間,並且在該空間內創建至少與一條流水線(即默認開啓一個線程); 可是建立線程,就是在一個車間內造出一個新的流水線,無需申請基礎空間,因此建立開銷小) """
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 12:05 PM "" """ 23-進程與線程的區別: 一、開進程的開銷遠大於開線程; 二、同一進程內的多個線程共享該進程的地址空間 """ #區別1; import time import random from threading import Thread from multiprocessing import Process def piao(name): print('%s piaoing'%name) time.sleep(random.randrange(1,3)) print('%s piao ended'%name) if __name__ == '__main__': # p1 = Process(target=piao, args=('cuixiaozhao',)) # p1.start() """ 主線程1 cuixiaozhao piaoing cuixiaozhao piao ended """ t1 = Thread(target= piao,args=('cuitianqing',)) t1.start() print('主線程1') """ cuitianqing piaoing 主線程1 cuitianqing piao ended """ #區別2; from threading import Thread from multiprocessing import Process n = 100 def task2(): global n n = 0 if __name__ == '__main__': # p1 = Process(target=task2,) # p1.start() # p1.join()#等待子進程運行完成,結果爲:主線程 100 t1 = Thread(target= task2,) t1.start()#主線程 0 t1.join() print('主線程',n) #區別3,瞅一眼pid from threading import Thread from multiprocessing import Process,current_process import os def task3(): #print(current_process().pid)#7428 print('子進程PID:%s 父進程的PPID:%s'%(os.getpid(),os.getppid()))#子進程PID:7760 父進程的PPID:19624 if __name__ == '__main__': # p1 = Process(target= task3,) # p1.start() t1 = Thread(target=task1,) t1.start() #print('主線程',current_process().pid)#主線程 19664 print('主進程',os.getpid())#主進程 7760 #區別4,瞅一眼pid from threading import Thread import os def task4(): print('子線程PID:%s '%(os.getpid()))#子線程PID:12248 if __name__ == '__main__': t1 = Thread(target=task4,) t1.start() print('主線程',os.getpid())#主線程 12248 #注意:其實沒有子線程PID,線程都是相同級別的,你們地位相等,爲了便於理解,纔在此處稱之爲:子線程;
Thread實例對象的方法 # isAlive(): 返回線程是否活動的。 # getName(): 返回線程名。 # setName(): 設置線程名。 threading模塊提供的一些方法: # threading.currentThread(): 返回當前的線程變量。 # threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啓動後、結束前,不包括啓動前和終止後的線程。 # threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 5:12 PM from threading import Thread,current_thread,active_count,enumerate import time def task(): print('%s is runing'%current_thread().getName()) time.sleep(2) print('%s is done'%current_thread().getName()) if __name__ == '__main__': t = Thread(target= task,name='子線程1') t.start() #t.setName('兒子線程1') #current_thread().setName('主線程') #print(t.is_alive())#返回值爲True或者False #print(t.isAlive())#返回值爲True或者False #print(t.getName()) #print('主線程',current_thread().getName()) #t.join() print(active_count()) print(enumerate())#[<_MainThread(MainThread, started 10096)>, <Thread(子線程1, started 14432)>]
不管是進程仍是線程,都遵循:守護xxx會等待主xxx運行完畢後被銷燬;
1)須要強調的是:運行完畢並不是終止運行;
一、對主進程來講,運行完畢指的是主進程代碼運行完畢; 二、對主線程來講,運行完畢指的是主線程所在的進程內全部非守護線程通通運行完畢,主線程纔算運行完畢;
2)詳細解釋;
一、主進程在其代碼結束後就已經算運行完畢了(守護進程在此時就被回收),而後主進程會一直等非守護的子進程都運行完畢後回收子進程的資源(不然會產生殭屍進程),纔會結束; 二、主線程在其餘非守護線程運行完畢後纔算運行完畢(守護線程在此時就被回收)。由於主線程的結束意味着進程的結束,進程總體的資源都將被回收,而進程必須保證非守護線程都運行完畢後才能結束;
3)驗證一下吧!
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 5:27 PM "" """ 25-守護線程 """ from threading import Thread import time def sayhi(name): time.sleep(1) print('%s say hello'%name) if __name__ == '__main__': t = Thread(target= sayhi,args= ('cuixiaozhao',)) #t.setDaemon(True)#必須在t.start()以前設置; t.daemon = True #做用同上; t.start() print('主線程') #print(t.isAlive()) print(t.is_alive())#做用同上; from threading import Thread import time def foo(): print(123) time.sleep(1) print('end123') def bar(): print(456) time.sleep(3) print('end456') """ 123 456 --------main-------- end123 end456 """ if __name__ == '__main__': t1 = Thread(target= foo) t2 = Thread(target=bar) t1.daemon = True t1.start() t2.start() print('main'.center(20,'-'))
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # __Author__:TQTL911 # Version:python3.6.6 # Time:7/20/2018 5:47 PM "" """ 26-互斥鎖-由並行改成串行,犧牲了性能,保證了數據安全; """ #mutex 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() 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) """ 小結: 一、犧牲了效率; 二、保證了數據安全; """