博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多任务(进程线程)
阅读量:3961 次
发布时间:2019-05-24

本文共 4131 字,大约阅读时间需要 13 分钟。

我们先来了解一下学习知识点

  • 多任务:理解什么是多任务,为什么使用多任务
  • 进程:理解什么是进程,怎么使用进程完成多任务
  • 线程:理解什么是进程,怎么使用进程完成多任务
  • 注意事项:理解进程和线程的联系和区别,以及使用中的注意事项

一、多任务

我们之前写的代码,以函数为例, 都是先执行完一个函数之后,才能执行下一个函数,但实际情况是, 我们需要多个函数同时进行。同一时间段内同时执行多个任务(函数或方法),就是多任务

多任务有两种表现形式:并发和并行

现在我们的计算机CPU都是多核CPU,我们之前写的代码是从上往下单任务执行的,只能使用CPU中的一个核心,使用多任务可以充分利用CPU多个核心的计算能力,提高执行效率

并发:CPU核心数小于任务数,CPU轮流(交叉)执行多个任务

并行*CPU核心数大于等于任务数,每个CPU核心可以单独执行一个任务

二、进程

从代码开始运行起来我们就称之为进程,所有代码执行完毕,进程结束

代码执行需要向操作系统申请内存资源,而进程是操作系统资源分配的最小单位,也就是说每启动一个进程,操作系统都会给其分配一定的运行资源(内存资源)保证进程的运行

2.1多进程的使用:

程序运行起来, 在所有代码执行之前,会先默认创建一个主进程(即内存资源分配的过程),该进程会默认包含一个线程(即主线程),代码的执行实际上是由线程完成的。

使用多进程,其实就是由主进程,创建了多个子进程,每个子进程也都有对应要执行的任务

# 导入进程包import multiprocessing# 创建子进程对象并指定执行的任务sub_process = multiprocessing.Process (target=任务名)# 启动子进程执行任务sub_process.start()
import multiprocessingimport time# 任务1def task1(count):    for i in range(count):        print("任务1执行中..")        time.sleep(0.2)# 任务2def task2(num):    for i in range(num):        print("任务2执行中..")        time.sleep(0.2)if __name__ == '__main__':    # group: 表示进程组,目前只能使用None    # target: 表示执行的目标任务名(函数名、方法名)    # name: 进程名称, 默认是Process-1, .....    # args: 以元组的方式给任务传入参数    # kwargs: 表示以字典方式传入参数    sub_process1 = multiprocessing.Process(target=task1, args=(5,))    sub_process2 = multiprocessing.Process(target=task2, kwargs={
"num": 3}) # 启动子进程执行对应的任务 sub_process1.start() sub_process2.start()

2.2 获取进程编号

获取进程编号的目的是验证主进程和子进程的关系,可以得知子进程是由那个主进程创建出来的。

获取进程编号的两种操作

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

2.3、进程的注意点

  1. 进程之间不共享全局变量
  2. 多进行的执行是无序的
  3. 主进程会等待所有的子进程执行结束再结束
    • 设置守护主进程方式: 子进程对象.daemon = True
    • 销毁子进程方式: 子进程对象.terminate()
    • 进程同步:子进程对象.join()

三、线程

线程是cpu调度的最小单位,是代码的真正执行者,每个进程至少都有一个线程,而这个线程就是我们通常说的主线程

3.1多线程的使用:

import threadingimport time# 任务1def task1(count):    for i in range(count):        print("任务1执行中..")        time.sleep(0.2)# 任务2def task2(num):    for i in range(num):        print("任务2执行中..")        time.sleep(0.2)if __name__ == '__main__':    # group: 表示线程组,目前只能使用None    # target: 表示执行的目标任务名(函数名、方法名)    # name: 线程名称, 默认是Process-1, .....    # args: 以元组的方式给任务传入参数    # kwargs: 表示以字典方式传入参数    sub_thread1 = threading.Thread(target=task, args=(5,))    sub_thread2 = threading.Thread(target=task, kwargs={
"num": 3}) # 启动子线程执行对应的任务 sub_thread1.start() sub_thread2.start()

3.2、线程的注意点

  1. 线程之间执行是无序的

  2. 线程之间共享全局变量

  3. 线程之间共享全局变量数据容易出现错误问题

  4. 主线程会等待所有的子线程执行结束再结束

    • 设置守护主线程的方式:

      • sub_thread = threading.Thread(target=task, daemon=True)
      • sub_thread.setDaemon(True)
    • 线程同步:子线程对象.join()

3.3、互斥锁

在编程中,为了避免共享数据出现错误,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象

互斥锁的使用
# 创建锁mutex = threading.Lock()# 上锁mutex.acquire()# 释放锁mutex.release()

注意点:

  • acquire和release方法之间的代码同一时刻只能有一个线程去操作
  • 如果在调用acquire方法的时候 其他线程已经使用了这个互斥锁,那么此时acquire方法会堵塞,直到这个互斥锁释放后才能再次上锁。
  • 互斥锁避免资源竞争
  • 互斥锁阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了
  • 可能会造成死锁

四、进程和线程比较

1.进程是操作系统资源分配的最小单位,线程是CPU调度的最小单位

2.线程依附于进程,没有进程就没有线程,一个进程默认提供一个线程(主线程),进程可以创建多个线程
3.进程不共享全局变量,同一个进程中的线程共享全局变量(资源竞争–>互斥锁,互斥锁可能产生死锁)
4.进程开销大但可以利用多核(并行),线程开销小但不能利用多核(并发)

1.多任务

概念:在同一时间段内执行多个任务好处呢就是 充分利用CPU,提高执行效率表现形式:1.并发	CPU在一段时间内交替执行多个任务.		2.并行	CPU在一段时间内只执行一个任务, 利用多个CPU完成执行多任务的功能

2.进程

概念:代码运行起来我们就称之为进程	 是操作系统资源分配的最小单位	 进程间不共享全局变量使用方式:1导包-import multiprocessing2创建子进程:无参数 p = multiprocessing.Process(target=目标函数)		  元组方式传参:p = multiprocessing.Process(target=目标函数, args=(1,))		  字典方式传参:p = multiprocessing.Process(target=目标函数, kwargs={"num": 1})3.启动子进程:p.start()获取进程编号	获取当前进程编号:os.getpid()			获取父进程编号:os.getppid()主进程与子进程的执行顺序:	正常情况下主进程会等待子进程执行结束后再结束	设置守护主进程主进程代码执行完毕, 会关闭该子进程	销毁子进程	子进程对象.terminate()	等待子进程结束	子进程对象.join()	多进程执行是无序的

3.线程

概念:线程是CPU调度的最小单位	线程依附于进程,一个进程默认提供一个线程(主线程),进程可以创建多个线程	一个进程中的所有线程共享全局变量使用方式:	导包	import threading	创建子线程	无参数:t = threading.Thread(target=目标函数)				元组方式传参:t = threading.Thread(target=目标函数, args=(1,))				字典方式传参:t = threading.Thread(target=目标函数, kwargs={"num": 1})启动子线程:t.start()主线程与子线程的执行顺序:	正常情况下主线程会等待子线程执行结束后再结束	设置守护主线程主线程代码执行完毕, 会关闭该子线程	(t = threading.Thread(target=目标函数, daemon=True))	(线程对象.setDaemon(True))	多线程执行是无序的

4.进程线程比较

1.进程是操作系统资源分配的最小单位,线程是CPU调度的最小单位2.线程依附于进程,没有进程就没有线程,一个进程默认提供一个线程(主线程),进程可以创建多个线程3.进程不共享全局变量,同一个进程中的线程共享全局变量(资源竞争-->互斥锁,互斥锁可能产生死锁)4.进程开销大但可以利用多核(并行),线程开销小但不能利用多核(并发)

转载地址:http://evezi.baihongyu.com/

你可能感兴趣的文章
hibernate 自动导入sql 文件import.sql 国际化编码的问题的解决方案
查看>>
第七颗头骨 & 忘魂花 凤凰
查看>>
李小龙哲学之言
查看>>
[心情] 如果有一天
查看>>
[Linux] 常用 linux 系统命令及维护备忘
查看>>
[Linux] 关于 Ext4 HowTo
查看>>
[杂记] 新年物语&关于Mysql引擎性能测试
查看>>
[心得] 近期更新&关于Infobright
查看>>
[杂记] 流量统计 & 短信接口
查看>>
[中间件] 消息处理利器 ActiveMQ 的介绍 & Stomp 协议的使用
查看>>
[设计] 原型界面设计利器 Balsamiq Mockups 推荐
查看>>
[闲话] 在西方的程序员眼里,东方的程序员是什么样的
查看>>
[管理] 成功之路的探寻 —— “三力” 理论
查看>>
[连载] Socket 深度探索 4 PHP (一)
查看>>
[无线] Android 系统开发学习杂记
查看>>
[无线] 浅析当代 LBS 技术
查看>>
[杂感] 缅怀乔布斯
查看>>
[无线] 让Android支持cmwap上网
查看>>
[无线] AndroidManifest.xml配置文件详解
查看>>
[移动] Mosquitto简要教程(安装/使用/测试)
查看>>