XX学Python·进程与线程

多任务编程-进程

  • 多任务执行方式

    • 并发:在一段时间内交替去执行任务

    • 并行:多核cpu每个cpu执行一个任务。注:任务>cpu时,每个cpu并发执行多个任务

  • 进程:计算机中的程序关于某数据集合上的一次运行活动,是操作系统资源(内存)分配的基本单位。一个程序运行后至少有一个进程,一个进程至少有一个线程。

  • 一个进程就开辟一块内存空间,多线程是利用一个内存空间

  • 多进程的基本使用:

# def login():
#     print('登录')
#
#
# if __name__ == '__main__':
#     login()
#     login()
# # 上面相当于在一个进程里面执行了多次方法。同一内存块里。

# 使用多进程的形式完成多次调用。相当于把程序复制后在不同的内存空间单独执行。
import multiprocessing  # 导入多进程模块


def login():
    print('登录')


# p1 = multiprocessing.Process(target=login())
# p1.start()
# 上面没放入if __name里运行报错,系统认为原有方法要执行一次,相当于重复运行。
if __name__ == '__main__':  # 多进程要放入if __name__里
    # Process括号里参数:
      #  group=None 指定分组,推荐使用默认None,
      #  target=None  指定要调用的函数名,常用
      #  name=None 指定进程名称,
      #  args=()元组传参注意一个元素('xx',), kwargs={}给函数传递参数
      #  daemon=None  指定守护进程
    # Process是一个类,注意不能用小写process
    # Process中target指定的是子进程要执行的任务,所以切记任务后面不要添加括号
    p1 = multiprocessing.Process(target=login)  # 创建了一个进程
    p2 = multiprocessing.Process(target=login)  # 相当于创建了一个实例对象
    p1.start()  # 运行进程指定对应函数业务逻辑
    p2.start()  # 使用start运行
  • 进程编号:子进程是由主进程创建出来的。

    • 获取当前进程编号:os.getpid()

    • 获取当前父进程编号:os.getppid()

import multiprocessing
import os


def login(name, password):
    print('名字:', name)
    print('密码:', password)
    print('登录')
    # 获取当前进程名称
    print('进程名称:', multiprocessing.current_process().name)
    # 获取当前进程编号,这里获取就是子进程
    print('子进程:', os.getpid())
    # 获取主进程编号,pid前面加了一个p,父进程
    print('子进程的父进程编号:', os.getppid())


if __name__ == '__main__':
    #  group=None 指定分组,推荐使用默认None
    #  target=None  指定要调用的函数名
    #  name=None 指定进程名称
    #  args=(), kwargs={}给函数传递参数,
    #  daemon=None  指定守护进程
    p1 = multiprocessing.Process(target=login, args=('Python', 123456), name='p1')
    p2 = multiprocessing.Process(target=login, kwargs={'name': 'xx', 'password': 123456}, name='p2')
    p3 = multiprocessing.Process(target=login, kwargs={'name': 'lsl', 'password': 123456}, name='p3')
    p1.start()
    p1.join()
    p2.start()
    p2.join()
    p3.start()
    p3.join()
    # 如果需要进程按照循序执行,需要用进程等待join方法,但一般不用。
    # 不用join,顺序就不一定,是cpu根据他的调用算法随机执行

    # 获取当前进程编号,使用os模块。这里获取的主进程编号。
    print('主进程:', os.getpid())
  • 进程注意点

    • 进程间不共享全局变量

    • 正常情况下主进程会等待子进程结束后在退出主进程

import multiprocessing

# 不共享全局变量
data_list = []


def write_data():
    # 往全局列表中写入数据
    for i in range(0, 50):
        print(i)
        data_list.append(i)
    print('write_data方法写入的数据为:', data_list)


def read_data():
    print('read_data方法读取的数据为:', data_list)


if __name__ == '__main__':
    # 创建多进程分别调用两个读写方法,验证全局变量是否共享数据
    p1 = multiprocessing.Process(target=write_data, daemon=True)
    p2 = multiprocessing.Process(target=read_data)

    p1.start()
    p2.start()

    # 正常情况下主进程会等待子进程结束后在退出主进程
    # 需求主进程结束后就结束子进程,不再进行等待
    # 两种形式实现 第一种设置守护进程参数daemon=True或 子进程对象.daemon=True
    # 第二种 主动关闭子进程
    p2.terminate()

    print('主进程读取的数据:', data_list)

多任务编程-线程

  • 线程:是操作系统运算调度的最小单位。被包含在进程之中,是进程实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

  • 线程的基本使用

# 导入线程模块
import threading


def func(data):
    print('线程使用')
    print(f'参数数据:{data}')
    # 获取当前执行线程的名称
    print('线程名称:', threading.current_thread().name)


if __name__ == '__main__':
    # 创建线程
    # group = None, 使用默认
    # target = None,  指定函数方法
    # name = None, 指定线程名称
    # args = (), kwargs = None, 传递参数
    # daemon = None 设置守护线程
    t1 = threading.Thread(target=func, args=('python',), name='t1')
    t2 = threading.Thread(target=func, kwargs={'data': 'itcast'}, name='t2')
    # 启动运行线程
    t1.start()
    t2.start()
  • 线程注意点

    • 线程执行是无序的,根据cpu随机调度

    • 主线程会等待子线程结束后在结束:指定守护线程或线程对象.setDaemon(True),当主线程结束后自动结束子线程

    • 线程间共享全局变量。但要注意无序执行导致的数据错乱,使用join等待

import threading
data = 0


def func1():
    global data
    for i in range(0, 1000000):
        data += 1
    print(f'函数1的累加结果:{data}')


def func2():
    global data
    for i in range(0, 1000000):
        data += 1
    print(f'函数2的累加结果:{data}')


if __name__ == '__main__':
    # 创建两个线程进程累加
    t1 = threading.Thread(target=func1)
    t2 = threading.Thread(target=func2)
    # 通过join的形式让函数顺序执行
    t1.start()
    t1.join()
    t2.start()
    t2.join()
    print(f'主线程的结果展示:{data}')
posted @ 2022-10-04 23:03  PORTB  阅读(20)  评论(0编辑  收藏  举报