28.并发编制【五】管道与多线程

【一】管道

1)介绍

from multiprocessing import Pipe

# 创建管道
left_pipe,right_pipe = Pipe()
# 返回管道两端的连接对象,需在产生Process对象之前产生管道
# 默认参数dumplex:默认管道是全双工的
# 若为False,left_pipe只能用于接收,right_pipe只能用于发送

2)主要方法

# 接收数据(一端关闭,另一端取数据)
left_pipe.close()
rght_pipe.recv()
rght_pipe.close()
# 发送数据
right_pipe.close()
left_pipe.send()
left_pipe.close()

3)示例

from multiprocessing import Pipe, Process

def producer(name, p_conn):
    # 获取两个管道
    left_pipe, right_pipe = p_conn
    # 放数据(关一个,再通过另一个管道传输)
    right_pipe.close()
    for i in range(5):
        i += 1
        data = f'生产者{name}生产了第{i}个商品'
        print(data)
        left_pipe.send(data)
    # 关闭管道
    left_pipe.close()

def customer(name, p_conn):
    # 获取两个管道
    left_pipe, right_pipe = p_conn
    # 取数据(关一个,再通过另一个管道取数据)
    left_pipe.close()
    while True:
        data = right_pipe.recv()
        print(f'{name}购买了---{data}')
        if not data:
            break
    right_pipe.close()

if __name__ == '__main__':
    # 创建管道对象
    pipe = Pipe()
    # 创建生产者和消费者
    producer_1 = Process(target=producer, args=('PR_1', pipe))
    producer_1.start()
    customer_1 = Process(target=customer, args=('CU_1', pipe))
    # 创建守护进程
    customer_1.daemon = True
    customer_1.start()
    producer_1.join()
# 生产者PR_1生产了第1个商品
# 生产者PR_1生产了第2个商品
# 生产者PR_1生产了第3个商品
# 生产者PR_1生产了第4个商品
# 生产者PR_1生产了第5个商品
# CU_1购买了---生产者PR_1生产了第1个商品
# CU_1购买了---生产者PR_1生产了第2个商品
# CU_1购买了---生产者PR_1生产了第3个商品
# CU_1购买了---生产者PR_1生产了第4个商品
# CU_1购买了---生产者PR_1生产了第5个商品

【二】多线程理论

1)线程概念

  • 在操作系统中,每一个进程都有一块内存空间地址
  • 线程:在进程内部开设的处理程序的进程
    • 操作系统 --> 运行一个程序叫进程 ---> 进程里面又开了一个进程为线程
  • 进程只是用来把资源集中到一起,线程 才是cpu上的执行单位
  • 多线程:就是在进程CPU处理多个任务的逻辑

1.小结

  • 进程(资源单位)
    • 就是车间
    • 存储设备及资源,
  • 线程(执行单位)
    • 就是里面的流水线
    • 负责对数据进行加工和处理

进程和线程都是抽象的概念

2)创建开销问题

  • 进程的创建开销 >> 线程的创建开销

3)进程和线程之间的关系

  • 进程与进程之间是竞争关系

  • 线程与线程之间是协调关系

4)区别

  • 线程共享创建它的进程的地址空间; 进程具有自己的地址空间。

  • 线程可以直接访问其进程的数据段; 进程具有其父进程数据段的副本。

  • 线程可以直接与其进程中的其他线程通信; 进程必须使用进程间通信与同级进程进行通信。

  • 新线程很容易创建; 新进程需要复制父进程。

  • 线程可以对同一进程的线程行使相当大的控制权。 进程只能控制子进程。

  • 对主线程的更改(取消,优先级更改等)可能会影响该进程其他线程的行为; 对父进程的更改不会影响子进程。

5)线程优点

  • 减少了资源的消耗
  • 同一个进程下的多个线程资源共享

【三】多线程的两种操作

1)直接调用 Thread 方法

from threading import Thread
import time, random


def work(name):
    time_sleep = random.randint(1, 5)
    print(f'{name}将持续{time_sleep}S')
    time.sleep(time_sleep)
    print(f'{name}结束')


def thread_work():
    task_list = []
    for i in range(5):
        task = Thread(target=work, args=(f'ST{i}',))
        task.start()
        task_list.append(task)
    for task in task_list:
        task.join()


if __name__ == '__main__':
    print('---开始---')
    start_time = time.time()
    thread_work()
    end_time = time.time()
    print(f'---总耗时{end_time - start_time}---')
# ---开始---
# ST0将持续1S
# ST1将持续2S
# ST2将持续5S
# ST3将持续5S
# ST4将持续2S
# ST0结束
# ST1结束
# ST4结束
# ST3结束
# ST2结束
# ---总耗时5.0015106201171875---

2)继承Thread 父类

from threading import Thread
import time, random

class MyThread(Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        time_sleep = random.randint(1, 5)
        print(f'{self.name}将持续{time_sleep}S')
        time.sleep(time_sleep)
        print(f'{self.name}结束')

def thread_work():
    task_list = []
    for i in range(5):
        task = MyThread(name=f'ST{i}')
        task.start()
        task_list.append(task)
    for task in task_list:
        task.join()

if __name__ == '__main__':
    print('---开始---')
    start_time = time.time()
    thread_work()
    end_time = time.time()
    print(f'---总耗时{end_time - start_time}---')
# ---开始---
# ST0将持续1S
# ST1将持续2S
# ST2将持续3S
# ST3将持续5S
# ST4将持续4S
# ST0结束
# ST1结束
# ST2结束
# ST4结束
# ST3结束
# ---总耗时5.002225875854492---

【四】线程之间共享数据

from threading import Thread
from multiprocessing import Process
num = 0

def worker(name):
    global num
    print(f'{name}改前:{num}')
    num += 10
    print(f'{name}改后:{num}')

# 进程之间的数据共享
def main_process():
    task_list = []
    for i in range(3):
        task = Process(target=worker, args=(f'ST{i}',))
        task.start()
        task_list.append(task)
        for task in task_list:
            task.join()

# 线程之间的数据共享
def main_thread():
    task_list = []
    for i in range(3):
        task = Thread(target=worker, args=(f'ST{i}',))
        task.start()
        task_list.append(task)
        for task in task_list:
            task.join()

if __name__ == '__main__':
    main_process()
    # ST0改前:0
    # ST0改后:10
    # ST1改前:0
    # ST1改后:10
    # ST2改前:0
    # ST2改后:10
    main_thread()
    # ST0改前:0
    # ST0改后:10
    # ST1改前:10
    # ST1改后:20
    # ST2改前:20
    # ST2改后:30
posted on 2024-05-28 20:16  晓雾-Mist  阅读(55)  评论(0)    收藏  举报