【python线程,进程,协程】

1、线程,进程是什么,协程是什么

  • 线程和进程都是操作系统里的概念

  • 进程:进程是操作系统进行资源分配和调度的基本单位。可以把进程想象成一个独立的工作区域,里面包含了程序运行所需的所有资源,比如内存、文件、设备等。每个进程都有自己的地址空间,所以它们之间是相互独立的。比如电脑上打开谷歌浏览器,操作系统就会去使用进程运行。
    在这里插入图片描述

  • 线程:进程是一个独立的工作区域,线程就是这个工作区域的员工,负责更具体的工作内容。同一个进程内的多个线程共享该进程的地址空间和其他资源,所以它们之间的通信和数据共享相对简单。线程就是进程里的面的一个执行单元,只能包含在进程中。

  • 协程(coroutine):python中协程是线程里的一部分,可以理解为一个微型的线程,如下图。

在这里插入图片描述

小结:线程是进程里的,协程是线程里的。进程向操作系统去申请一个独立的资源。线程在进程里,去调度进程申请到的资源。

2、多进程和多线程

1、当你在电脑上,同时打开浏览器开启一个网页,和游戏的时候,就是开启了多任务,这个是通过多进程是实现的。然后 你的浏览器的进程具体是内部的去用多线程去实现的,,而在每个线程内部,可能会使用协程(coroutines)来进一步提高执行效率。

进程:进程和进程之间,资源不共享
线程:线程是操作系统进行调度的最小单位,线程因为是进程内部的一个单元,所以,一个进程内部的线程和线程是资源共享的。

协程: 协程是线程内部的一个单元,一个线程内部的协程,协程和协程之间,共享这个线程内部的资源
听起来,线程和协程是一样的。
区别在于,一个进程内部的线程资源虽然是共享的,但是线程之间调用的话,因为是操作系统调度的,需要切换上下文信息,这个很浪费时间,但是协程共享线程的资源是不需要切换的。并且协程的切换是由编程者控制的,因此可以减少无效的调度,提高执行效率。(可以搜一下,什么是上下文信息管理,以及协程之间切换的步骤)

3、线程和多线程的实现

在Python中如果想使用线程实现多任务,可以使用thread模块 但是它比较底层,即意味着过程较为复杂不方便使用;推荐使用threading模块,它是对thread做了一些包装的,可以更加方便使用

3.1如果不用多线程,只是单线程运行
import time


def say_hello():
    print("今天又是美好的一天")
    time.sleep(1)


for i in range(5):
    say_hello()

3.2使用多线程
import threading 
import time 


def say_hello(): 
    print("今天又是美好的一天") 
    time.sleep(1) 


for i in range(5): 
    t = threading.Thread(target=say_hello) 
    t.start()  # 启动线程,即让线程开始执行 

分别运行上面两个程序,观察运行的结果

  • 可以明显看出使用了多线程并发的操作,花费时间要短很多
  • 当调用start()时,才会真正的创建线程,并且开始执行
3.3 同时执行多个不同的任务
import threading
from time import sleep, ctime


def sing():
    for i in range(3):
        print("正在唱歌...%d" % i)
        sleep(1)


def dance():
    for i in range(3):
        print("正在跳舞...%d" % i)
        sleep(1)


print('---开始---:%s' % ctime())
t1 = threading.Thread(target=sing)
t2 = threading.Thread(target=dance)
t1.start()
t2.start()
sleep(5)  # 屏蔽此行代码,试试看,程序是否会立马结束?
print('---结束---:%s' % ctime())

小结:

如果在一个程序中需要有多个任务一起执行,可以将每个任务单独放到一个函数中
使用threading.Thread创建一个对象,注意实参target需要指定为刚刚定义的函数名(不要写上小括号,那表示调用函数了)
调用threading.Thread返回的对象中的start方法(会让这个线程开始运行)

主线程会等待所有的子线程结束后才结束,所以当屏蔽sleep(5) 这一行,虽然 print(‘—结束—:%s’ % ctime()) 这一句执行完了,还是会等前面的线程执行完成才终止这个程序。

3.4 多线程执行的顺序不确定
import threading
from time import sleep, ctime   


def test1():   
    """
    这是一个单独的任务   
    """
    for i in range(10):    
        print("任务1...%d" % i)    
        sleep(0.1)    

        
def test2():    
    """
    这是另外一个单独的任务    
    """
    for i in range(5):    
        print("任务2...%d" % i)    
        sleep(0.2)    

        

t1 = threading.Thread(target=test1)    
t2 = threading.Thread(target=test2)    

t1.start()    
t2.start()    

小结:

当python程序中有多个任务需要被执行时,这些任务需要等待操作系统的调度(即操作系统安排接下来要执行哪个任务),因为每次运行程序时的环境(例如上次运行时 除了这个python程序之外还有QQ、微信在运行,而这次运行时没有QQ只有微信在运行都会影响操作系统的调度策略)不一样,所以多次运行同一个python程序时任务执行的先后顺序是不同的

3.5查看线程数量(了解)
import threading 
from time import sleep,ctime 

def sing(): 
    for i in range(3): 
        print("正在唱歌...%d" % i) 
        sleep(1)

def dance():  
    for i in range(3):  
        print("正在跳舞...%d" % i)  
        sleep(1)  


print('---开始---:%s' % ctime())  
t1 = threading.Thread(target=sing)  
t2 = threading.Thread(target=dance)  
t1.start()  
t2.start()  

while True:  
    # threading.enumerate()能够得到当前这个程序中正在运行的所有任务,是一个列表


    length = len(threading.enumerate())  
    print('当前运行的线程数为:%d' % length)  
    if length <= 1:  
        break  
        # 延时一会,等等其他线程执行  
        sleep(0.5)  

小结:

使用threading.enumerate()能够得到当前程序在运行时,所有的线程信息,以列表的方式返回
我们可以让主线程(程序运行后的默认线程),判断threading.enumerate()返回的线程数量,如果只有1个线程,那么就表示当前主线程自己,意味着没有其他的子线程(使用threading创建的那些线程),此时就可以结束主线程,只要主线程结束 那么这个程序也就结束了

4、进程和多进程的实现

线程是用的是threading这个模块,进程使用的是process这个模块
单进程:
如果我们不创建新的进程,单独运行一个代码,就是一个单进程,只有使用process这个模块去生成其余的进程,就是多进程了。

多进程代码的实现:

from multiprocessing import Process 
import time 
 
def test(): 
    """子进程单独执行的代码""" 
    while True: 
        print('---test---') 
        time.sleep(1) 
 
if __name__ == '__main__': 
    p=Process(target=test) 
    p.start()创建一个子进程,开始运行上面的test这个函数
    # 主进程单独执行的代码 
    while True: 
        print('---main---') 
        time.sleep(1) 

小结:
1、 通过额外创建一个进程,可以实现多任务
2、使用进程实现多任务的流程:

  • 创建一个Process对象,且在创建时通过target指定一个函数的引用
  • 当调用start时,会真正的创建一个子进程,然后运行上面target指定的函数

3、 Process创建的实例对象的常用方法

  • start():启动子进程实例(创建子进程)
  • is_alive():判断子进程是否还在活着
  • join([timeout]):是否等待子进程执行结束,或等待多少秒
  • terminate():不管任务是否完成,立即终止子进程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值