并发编程2

代码创建进程

创建进程的方式有哪些

  • 鼠标双击桌面一个应用图标
  • 代码创建

代码创建的两种方式

# 第一种代码创建进程的方式
from multiprocessing import Process
import time


def task(process_name):
    print('the subprocess %s is running' % process_name)
    time.sleep(3)
    print('the subprocess %s is over' % process_name)


if __name__ == '__main__':
    p = Process(target=task, args=('meta',))  # 创建一个进程对象
    p.start()  # 创建一个新的进程
    print('主进程')
# 第二种代码创建进程的方式
from multiprocessing import Process
import time


class MyProcess(Process):
    def __init__(self, process_name):
        self.process_name = process_name
        super().__init__()

    def run(self):
        print('the subprocess %s is running' % self.process_name)
        time.sleep(3)
        print('the subprocess %s is over' % self.process_name)


if __name__ == '__main__':
    p = MyProcess('mi_chat')
    p.start()
    print('主进程')

进程循环

# 客户端
import socket


client = socket.socket()
client.connect(('127.0.0.1', 8066))

count = 1
send_msg = input('请输入发送的内容>>>:').strip()
while count < 9:
    client.send(send_msg.encode('utf8'))
    data = client.recv(1024)
    count += 1
    print(data.decode('utf8'))
# 服务端
import socket
from multiprocessing import Process


def get_server():
    server = socket.socket()
    server.bind(('127.0.0.1', 8066))
    server.listen(4)
    return server


def talk(sock):
    count = 1
    while count < 9:
        count += 1
        data = sock.recv(1024)
        print(data.decode('utf8'))
        sock.send(f'我们已经收到您的消息'.encode('utf8'))


if __name__ == '__main__':
    server = get_server()
    count = 1
    while count < 9:
        sock, addr = server.accept()
        count += 1
        p = Process(target=talk, args=(sock,))
        p.start()

join方法

# join方法让主进程代码等待子进程代码运行完毕再执行

from multiprocessing import Process
import time


def task(process_name, time_arg):
    print(f'the subprocess: {process_name} is running')
    time.sleep(time_arg)
    print(f'the subprocess: {process_name} is over')


if __name__ == '__main__':
    p1 = Process(target=task, args=('qq', 1))
    p2 = Process(target=task, args=('tmall', 2))
    p3 = Process(target=task, args=('jd', 3))
    p4 = Process(target=task, args=('pxx', 4))
    start_time = time.time()
    p1.start()
    p2.start()
    p3.start()
    p4.start()
    p1.join()
    p2.join()
    p3.join()
    p4.join()
    end_time = time.time()
    sum_time = end_time - start_time
    print('主进程', f'总耗时:{sum_time}')  # 主进程 总耗时:4.281822919845581
# start一个join交替执行的情况
from multiprocessing import Process
import time


def task(process_name, time_arg):
    print(f'the subprocess: {process_name} is running')
    time.sleep(time_arg)
    print(f'the subprocess: {process_name} is over')


if __name__ == '__main__':
    p1 = Process(target=task, args=('qq', 1))
    p2 = Process(target=task, args=('tmall', 2))
    p3 = Process(target=task, args=('jd', 3))
    p4 = Process(target=task, args=('pxx', 4))
    start_time = time.time()
    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    p4.start()
    p4.join()
    end_time = time.time()
    sum_time = end_time - start_time
    print('主进程', f'总耗时:{sum_time}')  # 主进程 总耗时:10.786401271820068

进程间数据默认隔离

from multiprocessing import Process

nationality = 'China'


def task():
    global nationality
    nationality = 'USA'


if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    p.join()  # 目的是子进程代码运行结束再执行打印操作
    print(nationality)  # China

进程对象相关属性和方法

查看进程的方法

cmd

windows: tasklist
mac: ps -ef

python代码

current_process函数

# current_process函数
from multiprocessing import Process,current_process
import time


class MyProcess(Process):
    def __init__(self, process_name):
        self.process_name = process_name
        super().__init__()

    def run(self):
        print('the subprocess %s is running' % self.process_name)
        print(current_process().pid)
        time.sleep(3)
        print('the subprocess %s is over' % self.process_name)


if __name__ == '__main__':
    p = MyProcess('mi_chat')
    p.start()
    print('主进程')
    print(current_process().pid)

os模块

# os模块
from multiprocessing import Process,current_process
import time
import os

class MyProcess(Process):
    def __init__(self, process_name):
        self.process_name = process_name
        super().__init__()

    def run(self):
        print('the subprocess %s is running' % self.process_name)
        print(os.getpid())
        print(os.getppid())
        time.sleep(3)
        print('the subprocess %s is over' % self.process_name)


if __name__ == '__main__':
    p = MyProcess('mi_chat')
    p.start()
    print('主进程')
    print(os.getpid())

僵尸进程与孤儿进程

僵尸进程

主进程默认需要等待子进程结束才会结束,所有的子进程在运行结束之后都会变成僵尸进程
僵尸进程保留着pid和一些运行过程记录方便主进程查看,这些信息会被主进程回收

孤儿进程

子进程存活着,父进程意外死亡,子进程会被操作系统自动接管

守护进程

from multiprocessing import Process
import time


def task(process_name):
    print(f'子进程:{process_name}运行')
    time.sleep(2)
    print(f'子进程:{process_name}结束运行')


if __name__ == '__main__':
    p = Process(target=task, args=('qq_zone',))
    p.daemon = True
    p.start()
    print('process qq is over')

互斥锁

# 代码模拟抢票
import json
from multiprocessing import Process, Lock
import time
import random


# 查票
def search(name):
    with open(r'ticket_data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    print(f'{name}查询当前余票:%s' % data.get('ticket_num'))


# 买票
def buy(name):
    # 查询剩余票数
    with open(r'ticket_data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    time.sleep(random.randint(1, 2))
    # 判断是否还有余票
    if data['ticket_num'] > 0:
        data['ticket_num'] -= 1
        with open(r'ticket_data.json', 'w', encoding='utf8') as f:
            json.dump(data, f)
        print(f'{name}抢票成功')
    else:
        print(f'{name}抢票失败,没有余票')


def run(name, mutex):
    search(name)
    mutex.acquire()  # 抢锁
    buy(name)
    mutex.release()  # 放锁


if __name__ == '__main__':
    mutex = Lock()
    for i in range(1, 10):
        p = Process(target=run, args=('用户:%s' % i, mutex))
        p.start()
posted @ 2022-04-19 21:55  一梦便是数千载  阅读(21)  评论(0编辑  收藏  举报