最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

Python多任务教程

来源:博客园

一.并发和并行

  1. 多任务:一定时间段内,充分利用cpu资源,同时去执行多个任务

  2. 并发: 快速交替的 去执行多任务

  3. 并行: 真正同时的 去执行多任务 ,就是同时进行


    (相关资料图)

二.多进程

1.多进程入门

知识点:

  1. 进程含义: 运行中的程序

  2. 进程特点: cpu资源分配的 最小单位

  3. 多进程模块: multiprocessing

  4. 进程类: Process

使用步骤:

  1. 导包 : import multiprocessing

  2. 创建对象 : 子进程对象 = multiprocessing.Process(target=任务名)

  3. 开启进程 : 子进程对象.start()

示例:

import multiprocessingimport time# 任务1def dance():    for i in range(5):        time.sleep(0.1)        print("跳舞",i)# 任务2def sing():    for i in range(5):        time.sleep(0.3)        print("唱歌",i)# 多进程放到main内if __name__ == "__main__":    # 1.创建进程对象    p1 = multiprocessing.Process(target=dance)    p2 = multiprocessing.Process(target=sing)    # 2.开启进程    p1.start()    p2.start()

2.os模块获取进程编号

知识点:

获取当前进程id: os.getpid()   pid: processing id获取父进程id: os.getppid()   ppid: parent processing id

示例:

import multiprocessingimport osimport time# 任务1def dance():    print("dance子进程:", os.getpid(), os.getppid())    for i in range(5):        time.sleep(0.1)        print("跳舞",i)# 任务2def sing():    print("sing子进程:", os.getpid(),os.getppid())    for i in range(5):        time.sleep(0.3)        print("唱歌",i)# 多进程放到main内if __name__ == "__main__":    print("main主进程:",os.getpid())    # 1.创建进程对象    p1 = multiprocessing.Process(target=dance)    p2 = multiprocessing.Process(target=sing)    # 2.开启进程    p1.start()    p2.start()

3.Process()类的传参,2种方式

知识点:

  • args: 以元组方式传参 注意:如果只有一个参数需要加逗号, 如果多个参数顺序要任务参数顺序一致

  • kwargs: 以字典方式传参 注意:需要{k:v}形式传参,k必须和任务的形参名一致

示例:

import multiprocessingimport osimport time# 任务1def dance(num):    print("dance子进程:", os.getpid(), os.getppid())    for i in range(num):        time.sleep(0.1)        print("跳舞",i)# 任务2def sing(num):    print("sing子进程:", os.getpid(), os.getppid())    for i in range(num):        time.sleep(0.3)        print("唱歌",i)# 多进程放到main内if __name__ == "__main__":    print("main主进程:", os.getpid())    # 1.创建进程对象    p1 = multiprocessing.Process(target=dance,args=(5,))    p2 = multiprocessing.Process(target=sing,kwargs={"num":5})    # 2.开启进程    p1.start()    p2.start()

4.获取当前进程信息

知识点:

  1. 获取当前进程对象: multiprocessing.current_process()

  2. 获取当前进程name: multiprocessing.current_process().name

  3. 获取当前进程pid: multiprocessing.current_process().pid

示例:

import multiprocessing# 任务1def dance():    print("dance子进程对象:", multiprocessing.current_process())    print("dance子进程name:", multiprocessing.current_process().name)    print("dance子进程id:", multiprocessing.current_process().pid)# 任务2def sing():    print("sing子进程对象:", multiprocessing.current_process())    print("sing子进程name:", multiprocessing.current_process().name)    print("sing子进程id:", multiprocessing.current_process().pid)# 多进程放到main内if __name__ == "__main__":    print("main主进程对象:", multiprocessing.current_process())    print("main主进程name:", multiprocessing.current_process().name)    print("main主进程id:", multiprocessing.current_process().pid)    # 1.创建进程对象    p1 = multiprocessing.Process(target=dance,name="danceProcess")    p2 = multiprocessing.Process(target=sing,name="singProcess")    # 2.开启进程    p1.start()    p2.start()

5.注意事项

1. 多进程间不能共享全局变量:

import multiprocessingmylist = []# 写def write():    global mylist    mylist = [1,2,3,4,5]    print("write:",mylist) # [1, 2, 3, 4, 5]# 读def read():    global mylist    print("read:",mylist)  # []  说明多个进程间不共享全局变量# 多进程需要放到main内if __name__ == "__main__":    # 1.创建进程对象    p1 = multiprocessing.Process(target=write)    p2 = multiprocessing.Process(target=read)    # 2.开启进程    p1.start()    p2.start()

2. 主进程默认等待子进程结束再结束:

import multiprocessingimport time# 任务def task():    for i in range(10):        print("任务进行中...")        time.sleep(0.2)# 多任务if __name__ == "__main__":    # 1.创建进程对象    p1 = multiprocessing.Process(target=task)    # 2.开启进程    p1.start()    # 3.主进程等待0.5秒    time.sleep(0.5)    print("主进程中最后一行代码....")

2. 主进程默认等待子进程结束再结束:

import multiprocessingimport time# 任务def task():    for i in range(10):        print("任务进行中...")        time.sleep(0.2)# 多任务if __name__ == "__main__":    # 1.创建进程对象    p1 = multiprocessing.Process(target=task)    # 2.开启进程    p1.start()    # 3.主进程等待0.5秒    time.sleep(0.5)    print("主进程中最后一行代码....")

3. 多进程执行是无序的:

import multiprocessingimport time# 任务def show():    time.sleep(2)    print(multiprocessing.current_process().name)# 学习中遇到问题没人解答?小编创建了一个Python学习交流群:711312441# 多任务if __name__ == "__main__":    for _ in range(5):        # 创建进程对象        p = multiprocessing.Process(target=show)        # 开启进程        p.start()

6.设置子进程跟着主进程一起结束#

知识点:

方式1 设置子进程守护主进程:  子进程对象.daemon = True   注意: 需要在开启进程之前设置          :                          daemon/ˈdiːmən/守护进程方式2 手动销毁子进程     :  子进程对象.terminate()    terminate:结束,终止

1. 守护主进程:

import multiprocessingimport time# 任务def task():    for i in range(10):        print("任务进行中...")        time.sleep(0.2)# 多任务if __name__ == "__main__":    # 1.创建进程对象    p1 = multiprocessing.Process(target=task)    # 方式1: 开启子进程之前设置守护主进程    p1.daemon = True    # 2.开启进程    p1.start()    # 3.主进程等待0.5秒    time.sleep(0.5)    print("主进程中最后一行代码....")

2. 手动销毁子进程:

import multiprocessingimport time# 任务def task():    for i in range(10):        print("任务进行中...")        time.sleep(0.2)# 多任务if __name__ == "__main__":    # 1.创建进程对象    p1 = multiprocessing.Process(target=task)    # 2.开启进程    p1.start()    # 3.主进程等待0.5秒    time.sleep(0.5)    print("主进程中最后一行代码....")        # 方式2: 手动销毁子进程    p1.terminate()

三.多线程

1.多线程入门

知识点:

  1. 线程含义: 进程中 执行代码的 一个分支 (一个进程至少有一个线程)

  2. 线程作用: 线程是 cpu调度的 最小单位

  3. 多线程模块: threading

  4. 线程类: Thread

使用步骤:

  1. 导包 : import threading
  2. 创建对象 : 子线程对象 = threading.Thread(target=任务名)
  3. 开启进程 : 子线程对象.start()

示例:

import threading# 任务1def dance():    for i in range(5):        print("跳舞",i)# 任务2def sing():    for i in range(5):        print("唱歌",i)# 多任务if __name__ == "__main__":    # 1.创建子线程对象    t1 = threading.Thread(target=dance)    t2 = threading.Thread(target=sing)    # 2.开启线程    t1.start()    t2.start()

2.多线程的传参

知识点:

args: 以元组方式传参 注意:如果只有一个参数需要加逗号, 如果多个参数顺序要任务参数顺序一致

kwargs: 以字典方式传参 注意:需要{k:v}形式传参,k必须和任务的形参名一致

与多进程一模一样

示例:

import threading"""args: 以元组方式传参   注意:如果只有一个参数需要加逗号, 如果多个参数顺序要任务参数顺序一致kwargs: 以字典方式传参  注意:需要{k:v}形式传参,k必须和任务的形参名一致"""# 任务1def dance(num):    for i in range(num):        print("跳舞", i)# 任务2def sing(num):    for i in range(num):        print("唱歌", i)# 多任务if __name__ == "__main__":    # 1.创建子线程对象    t1 = threading.Thread(target=dance,args=(5,))    t2 = threading.Thread(target=sing,kwargs={"num":5})    # 2.开启线程    t1.start()    t2.start()

3.多线程注意事项

  1. 多线程是在一个进程中
import osimport threading"""args: 以元组方式传参   注意:如果只有一个参数需要加逗号, 如果多个参数顺序要任务参数顺序一致kwargs: 以字典方式传参  注意:需要{k:v}形式传参,k必须和任务的形参名一致"""# 任务1def dance(num):    print(f"dance子线程中当前进程pid:{os.getpid()}")    for i in range(num):        print("跳舞", i)# 任务2def sing(num):    print(f"sing子线程中当前进程pid:{os.getpid()}")    for i in range(num):        print("唱歌", i)# 多任务if __name__ == "__main__":    print(f"main主线程中当前进程pid:{os.getpid()}")    # 1.创建子线程对象    t1 = threading.Thread(target=dance,args=(5,))    t2 = threading.Thread(target=sing,kwargs={"num":5})    # 2.开启线程    t1.start()    t2.start()

2. 多线程是可以共享全局变量

import threadingmylist = []# 写def write():    global mylist    mylist = [1,2,3,4,5]    print("write:",mylist) # [1, 2, 3, 4, 5]# 读def read():    global mylist    print("read:",mylist)  # [1, 2, 3, 4, 5] 访问到了write线程修改后的内容说明多线程共享全局变量if __name__ == "__main__":    # 1.创建线程对象    t1 = threading.Thread(target=write)    t2 = threading.Thread(target=read)    # 2.开启线程    t1.start()    t2.start()

3. 主线程默认等待子线程结束再结束

import threadingimport time# 任务def task():    for i in range(10):        print("任务进行中...")        time.sleep(0.2)# 多任务if __name__ == "__main__":    # 1.创建线程对象    t = threading.Thread(target=task)    # 2.开启线程    t.start()    # 3.为了效果明显点,主线程等待0.5秒    time.sleep(0.5)    print("主线程中最后一行代码....")

4. 多线程是无序的

import threadingimport time# 任务def show():    time.sleep(1)    print(threading.current_thread().name)# 多任务if __name__ == "__main__":    for _ in range(5):        # 创建线程对象        p = threading.Thread(target=show)        # 开启线程        p.start()

4.设置守护主线程

知识点:

方式1: daemon属性        t.daemon = True       daemon/ˈdiːmən/守护进程    方式2: setDaemon()方法   t.setDaemon(True)

一个是属性,一个是方法,用哪个都可以

示例:

import threadingimport time# 任务def task():    for i in range(10):        print("任务进行中...")        time.sleep(0.2)# 多任务if __name__ == "__main__":    # 1.创建线程对象    t = threading.Thread(target=task)        # 方式1: daemon属性    # t.daemon = True    # 方式2: setDaemon()方法    t.setDaemon(True)    # 2.开启线程    t.start()    # 3.为了效果明显点,主线程等待0.5秒    time.sleep(0.5)    print("主线程中最后一行代码....")

5.获取当前线程信息

知识点:

  1. 获取当前线程对象:threading.current_thread()

  2. 获取当前线程name:threading.current_thread().name

  3. 获取当前线程id:threading.current_thread().native_id

示例:

import threadingdef dance():    print(f"dance当前线程对象:{threading.current_thread()}")    print(f"dance当前线程name:{threading.current_thread().name}")    print(f"dance当前线程id:{threading.current_thread().native_id}")def sing():    print(f"sing当前线程对象:{threading.current_thread()}")    print(f"sing当前线程name:{threading.current_thread().name}")    print(f"sing当前线程id:{threading.current_thread().native_id}")if __name__ == "__main__":    print(f"main当前线程对象:{threading.current_thread()}")    print(f"main当前线程name:{threading.current_thread().name}")    print(f"main当前线程id:{threading.current_thread().native_id}")    # 1.创建线程对象    t1 = threading.Thread(target=dance,name="DanceThread")    t2 = threading.Thread(target=sing,name="SingThread")    # 2.开启线程    t1.start()    t2.start()

6.线程安全问题

1. 出现的线程安全问题:

import threadingsum = 0def sum1():    global sum    for i in range(1000000):        sum += 1    print(sum) # 1114834def sum2():    global sum    for i in range(1000000):        sum += 1    print(sum)  # 1339347# 单任务不会出现问题 正常结果  1000000 2000000# 多任务出现了问题if __name__ == "__main__":    # 1.创建线程对象    t1 = threading.Thread(target=sum1)    t2 = threading.Thread(target=sum2)    # 2.开启线程    t1.start()    t2.start()

2. 锁机制解决线程安全问题:

import threadingsum = 0def sum1(lock):    lock.acquire() # 加锁    global sum    for i in range(1000000):        sum += 1    print(sum) # 1000000    lock.release() # 释放锁def sum2(lock):    lock.acquire()  # 加锁    global sum    for i in range(1000000):        sum += 1    print(sum)  # 2000000    lock.release()  # 释放锁# 单任务不会出现问题 正常结果  1000000 2000000# 多任务出现了问题 ,利用锁机制解决问题if __name__ == "__main__":    # 创建一个锁,保证两个任务用的是同一个锁    lock= threading.Lock()    # 1.创建线程对象    t1 = threading.Thread(target=sum1,args=(lock,))    t2 = threading.Thread(target=sum2,args=(lock,))    # 2.开启线程    t1.start()    t2.start()

3. join解决线程安全问题:

import threadingsum = 0def sum1():    global sum    for i in range(1000000):        sum += 1    print(sum)  # 1000000def sum2():    global sum    for i in range(1000000):        sum += 1    print(sum)  # 2000000# 学习中遇到问题没人解答?小编创建了一个Python学习交流群:711312441# 单任务不会出现问题 正常结果  1000000 2000000# 多任务出现了问题 ,利用join解决问题if __name__ == "__main__":    # 1.创建线程对象    t1 = threading.Thread(target=sum1)    t2 = threading.Thread(target=sum2)    # 2.开启线程    t1.start()    t1.join()  # t1线程告诉其他线程等我执行完,你们其他线程再执行    t2.start()

四.进程和线程对比

关系

  1. 线程是依附在进程里面的,没有进程就没有线程

  2. 一个进程默认提供一条线程,进程可以创建多个线程

区别

  1. 进程之间不共享全局变量
  2. 线程之间共享全局变量,但是要注意资源竞争的问题,解决办法是互斥锁或者线程同步
  3. 创建进程的资源开销要比创建线程的资源开销要大
  4. 进程是操作系统 资源分配 的基本单位,线程是 CPU调度 的基本单位
  5. 线程不能够独立执行,必须依存在进程中
  6. 多进程开发比单进程多线程开发稳定性要强

优缺点

进程优缺点:优点:可以用多核缺点:资源开销大

线程优缺点:优点:资源开销小缺点:不能使用多核

关键词: 全局变量 安全问题