1. 程式人生 > >線程進階

線程進階

bind 有一個 參數 conn 函數依賴 __name__ enc pos 釋放

在了解進程之後,我們可以做一個多線程的聊天室

服務端

import socket
from multiprocessing import Process

def talk(conn):
    conn.send(bconnected)
    ret = conn.recv(1024)
    print(ret)

if __name__ == __main__:
    sk = socket.socket()
    sk.bind((127.0.0.1, 8080))
    sk.listen()
    while True:
        conn,addr = sk.accept()
        p 
= Process(target=talk,args=(conn,)) p.start() conn.close() sk.close()

客戶端

import socket
sk = socket.socket()
sk.connect((127.0.0.1,8080))
ret = sk.recv(1024)
print(ret)
msg = input(>>>)
sk.send(msg.encode(utf-8))
sk.close()

我們不論建立幾個客戶端都可以做到和服務端互動,他們每一個都是自己獨立的線程

守護進程  子進程會在主進程結束時結束

# start  開啟一個進程
# join   用join可以讓主進程等待子進程結束

# 守護進程
# 守護進程會隨著主進程的代碼執行結束而結束
# 正常的子進程沒有執行完的時候主進程要一直等著
import time
from multiprocessing import Process
def func():
    print(--*10)
    time.sleep(15)
    print(--*10)

def cal_time():
    while True:
        time.sleep(1)
        print(過去了1秒)

if __name__
== __main__: p = Process(target=cal_time) p.daemon = True # 一定在開啟進程之前設置 p.start() p2 = Process(target=func) # 15s p2.start() for i in range(100): # 10s time.sleep(0.1) print(**i) p2.join() # 守護進程的進程的作用: # 會隨著主進程的代碼執行結束而結束,不會等待其他子進程 # 守護進程 要在start之前設置 # 守護進程中 不能再開啟子進程

進程的其他方法

import time
from multiprocessing import Process
# def func():
#     print(‘wahaha‘)
#     time.sleep(5)
#     print(‘qqxing‘)
# if __name__ == ‘__main__‘:
#     p = Process(target=func)
#     p.start()
#     print(p.is_alive())  #
#     time.sleep(0.1)
#     p.terminate()        # 關閉進程  異步
#     print(p.is_alive())  # ???
#     time.sleep(1)
#     print(p.is_alive())
# p.is_alive()   # 是否活著 True代表進程還在 False代表進程不在了
# p.terminate()  # 結束一個進程,但是這個進程不會立刻被殺死


# 屬性
# pid   查看這個進程 進程id
# name  查看這個進程的名字

# def func():
#     print(‘wahaha‘)
#     time.sleep(5)
#     print(‘qqxing‘)
# if __name__ == ‘__main__‘:
#     p = Process(target=func)
#     p.start()
#     print(p.name,p.pid)
#     p.name = ‘哇哈哈哈‘
#     print(p.name)

# class MyProcess(Process):
#     def run(self):
#         print(‘wahaha‘,self.name,self.pid)
#         time.sleep(5)
#         print(‘qqxing‘,self.name,self.pid)
# if __name__ == ‘__main__‘:
#     p = MyProcess()
#     p.start()
#     print(p.pid)

# 進程中的其他方法
# 守護進程 p.daemon = True
# 兩個方法 p.is_alive() p.terminate()
# 兩個屬性 p.pid p.name

鎖  在一個主線程開啟多個子線程時,這幾個子線程的數據是隔離的,但是當他們都與主進程互動時,難免會產生數據混亂,這種情況我們叫做

數據不安全,解決辦法就是在進程中加鎖

# from multiprocessing import Lock
# lock = Lock()
# lock.acquire()  # 需要鎖   拿鑰匙
# lock.acquire()  # 需要鎖   阻塞
#
# lock.release()  # 釋放鎖  還鑰匙

# 鎖 就是在並發編程中 保證數據安全

# 多進程 實現 並發

import json
import time
import random
from multiprocessing import Lock
from multiprocessing import Process

def search(i):
    with open(ticket) as f:
        print(i,json.load(f)[count])

def get(i):
    with open(ticket) as f:
        ticket_num = json.load(f)[count]
    time.sleep(random.random())
    if ticket_num > 0:
        with open(ticket,w) as f:
            json.dump({count:ticket_num-1},f)
        print(%s買到票了%i)
    else:
        print(%s沒票了%i)

def task(i,lock):
    search(i)   # 查看票
    lock.acquire()
    get(i)      # 搶票
    lock.release()

if __name__ == __main__:
    lock = Lock()
    for i in range(20):  # 20個人同時搶票
        p = Process(target=task,args=(i,lock))
        p.start()

當我們需要同時幾個進程的時候,就相當於多給幾個鑰匙,這種情況叫信號量

# 信號量
from multiprocessing import Semaphore
# sem = Semaphore(4)
# sem.acquire()  # 需要鑰匙
# print(0)
# sem.acquire()  # 需要鑰匙
# print(1)
# sem.acquire()  # 需要鑰匙
# print(2)
# sem.acquire()  # 需要鑰匙
# print(3)
# sem.release()
# sem.acquire()  # 需要鑰匙
# print(4)
import time
import random
from multiprocessing import Semaphore
from multiprocessing import Process
def sing(i,sem):
    sem.acquire()
    print(%s : 進入 ktv%i)
    time.sleep(random.randint(1,10))
    print(%s : 出 ktv%i)
    sem.release()
# 迷你唱吧  20個人,同一時間只能有4個人進去唱歌
if __name__ == __main__:
    sem = Semaphore(4)
    for i in range(20):
        Process(target=sing,args=(i,sem)).start()

event模塊

可以控制進程的阻塞

# 事件
# 所有的阻塞 都是同步
# recv accept input sleep
# 阻塞多個進程  異步阻塞
# lock 10進程
# 事件 —— 異步阻塞
# 事件 標誌 同時 是所有的進程 都陷入阻塞

from multiprocessing import Event   #事件
# e = Event() # 實例化一個事件  標誌/交通信號燈
# e.set()     # 將標誌變成非阻塞/交通燈變綠
# e.wait()    # 剛實例化出來的一個事件對象,默認的信號是阻塞信號/默認是紅燈
#             # 執行到wait,要先看燈,綠燈行紅燈停,如果在停的過程中燈綠了,
#             # 就變成非阻塞了
# e.clear()   # 將標誌又變成阻塞/交通燈變紅
#
# e.is_set() # 是否阻塞 True就是綠燈 False就是紅燈

# 紅綠燈

import time
import random
from multiprocessing import Process
from multiprocessing import Event
def traffic_light(e):
    while True:
        if e.is_set():
            time.sleep(3)
            print(紅燈亮)
            e.clear()      # 綠變紅
        else:
            time.sleep(3)
            print(綠燈亮)
            e.set()        # 紅變綠

def car(i,e):
    e.wait()
    print(%s車通過%i)

if __name__ == __main__:
    e = Event()   # 立一個紅燈
    tra = Process(target=traffic_light,args=(e,))
    tra.start()   # 啟動一個進程來控制紅綠燈
    for i in range(100):
        if i%6 == 0 :
            time.sleep(random.randint(1,3))
        car_pro = Process(target=car, args=(i,e))
        car_pro.start()

當我們想要在幾個子進程間調用數據時,使用隊列方法

# 進程之間的通信

# lock
# 1 lock.acquire
# 2 lock.acquire

# sem

# e


# ‘hello‘  --> 子進程
# 子進程1 ‘hello’ --> 子進程2

from multiprocessing import Queue
# q = Queue(3)
# q.put(1)
# q.put(2)
# q.put(3)
# q.put(4)
#
# print(q.get())
# print(q.get())
# print(q.get())
# print(q.get())  # 如果隊列裏已經沒有值了 就會阻塞等待有一個值

#1.進程之間通信 可以使用multiprocessing 的 Queue模塊
#2.隊列有兩種創建方式 第一種不傳參數 這個隊列就沒有長度限制 ;傳參數,創建一個有最大長度限制的隊列
#3.提供兩個重要方法;put get
#4.qsize

from multiprocessing import Process
from multiprocessing import Queue

# def q_put(q):
#     q.put(‘hello‘)
#
# def q_get(q):
#     print(q.get())
#
# if __name__ ==‘__main__‘:
#     q = Queue()
#     p = Process(target=q_put,args=(q,))
#     p.start()
#     p1 = Process(target=q_get, args=(q,))
#     p1.start()


# 通過隊列實現了 主進程與子進程的通信   子進程與子進程之間的通信
# 生產者消費者模型

# 我要生產一個數據 然後 給一個函數 讓這個函數依賴這個數據進行運算  拿到結果  —— 同步過程

# 做包子 和 吃包子
import time
def producer(q):  # 生產者
    for i in  range(100):
        q.put(包子%s%i)

def consumer(q): #  消費者
    for i in range(100):
        time.sleep(1)
        print(q.get())

if __name__ == __main__:
    q = Queue(10)   # 托盤
    p = Process(target=producer,args=(q,))
    p.start()
    c1 = Process(target=consumer, args=(q,))
    c2 = Process(target=consumer, args=(q,))
    c1.start()
    c2.start()

# 首先 對於內存空間來說 每次只有很少的數據會在內存中
# 對於生產與消費之間的不平衡來說
    # 增加消費者或者增加生產者來調節效率

線程進階