python:进程、线程

一、进程

1.多任务的执行方式:并发、并行;

并发:在一段时间内交替去执行任务。单核cpu处理多任务,操作系统轮流让各个软件交替执行。

并行:对于多核cpu处理多任务,操作系统会给cpu的每个内核安排一个执行的软件,多个内核是真正的一起运行软件。多核cpu是并行的执行软件,即:始终是多个软件同时运行。

2.进程的介绍

一个正在运行的程序或者软件就是一个进程。,它是操作系统进行资源分配的基本单位

进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程

3.进程的使用

#导入进程包
import multiprocessing

4.Process进程类的说明

multiprocessing.Process()是继承process.BaseProcess类的,BaseProcess来的初始化参数包括:

group、target、name、args、kwargs;其中target最为重要,表示执行的函数或者方法名;

5.Process创建的实例对象的常用方法:

start():启动子进程实例(创建子进程)

join():等待子进程执行结束

terminate():不管任务是否执行完毕,立即终止进程。

6.进程-》实例:实现多任务同时执行

主进程+子进程:

3个进程(主进程+2个子进程)的方式:

7.获取进程编号

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

1.获取当前进程编号2.获取当前父进程编号

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

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

#下面的代码,包括了getpid、getppid、multiprocessing.current_process()、start、kill

# -*-coding:utf-8-*-
#进程--实例
'''需求:实现同时执行两个target
'''
import multiprocessing,time,os
#target1:

def pro001():
    # 获取当前进程id
    pro001_process_id=os.getpid()
    # 查看当前代码是由哪个进程执行的multiprocessing.current_process()
    ppro001_process_id=os.getppid()#父进程id
    print("pro001_process_id:", pro001_process_id,ppro001_process_id, multiprocessing.current_process())
    for i in range(3):
        print('执行中……pro001')
        time.sleep(0.3)
        #kill杀死进程,数字9:强制
        os.kill(pro001_process_id,9)
def pro002():
    # 获取当前进程id
    pro002_process_id = os.getpid()
    #查看当前代码是由哪个进程执行的multiprocessing.current_process()
    print("pro002_process_id:", pro002_process_id, multiprocessing.current_process())
    for i in range(3):
        print("pro002在主进程中执行……")
        time.sleep(0.3)
if __name__ == '__main__':
    # 创建子进程(自己手动创建的进程成为子进程)
    process_1 = multiprocessing.Process(target=pro001,name='pro001')    # group:进程组,目前必须为None,否则报错;
    # 创建子进程(自己手动创建的进程成为子进程)
    process_2 = multiprocessing.Process(target=pro002)
    process_1.start()
    process_2.start()
    #获取当前进程id
    main_process_id = os.getpid()#因为这里执行没有指派子进程,所以获取的是主进程id
    print("main_process_id:",main_process_id)#main_process_id: 16412
    #但是,上面你只知其进程id,但不知是不是主进程,
    # 所以,需要获取当前进程对象,查看当前代码是由哪个进程执行的
    print("main_process_id:", main_process_id,multiprocessing.current_process())
    #结果:main_process_id: 1428 <_MainProcess name='MainProcess' parent=None started>

8、进程执行带参数的函数

# -*-coding:utf-8-*-
#进程带参数的函数执行
import multiprocessing

def show_info(name,age,msg):
    '''
    显示name,age,进程信息
    :param name:
    :param age:
    :return:
    '''
    print(name,":",age,msg,multiprocessing.current_process())

if __name__ == '__main__':
    #以元组方式传参,注意:元组中元素顺序与函数的参数一一对应
    sub_precess = multiprocessing.Process(target=show_info,args=("ithing",20,"进程args"))
    sub_precess.start()
    #以字典方式参数,注意:字典中的key与函数中的参数名要一致,没有顺序要求
    sub_precess2 = multiprocessing.Process(target=show_info,kwargs={"name":"李四","age":18,"msg":"进程kwargs"})
    sub_precess2.start()
    #元组、字典混合传参,注意每种方式传参给函数中的哪个参数,args要传入函数参数中的前面的
    sub_precess3 = multiprocessing.Process(target=show_info,args=("zhangsan",28,),kwargs={"msg":"进程kwargs、args"})
    sub_precess3.start()

9、进程之间不共享全局变量

创建一个子进程,其实是对主进程资源进行拷贝,子进程其实就是主进程的一个副本;子进程改变的数据,都是该进程内部的,对主进程、其他子进程无影响;下面的例子的结果:读取数据的进程打印的内容是不变的,不论改变数据的进程如何执行。

# -*-coding:utf-8-*-
#进程带参数的函数执行
import multiprocessing,time
#定义全局变量
data=list()
#改变全局变量
def add_data():
    for i in range(3):
        print(i)
        data.append(i)
        time.sleep(0.3)

#读取全局变量
def read_data():
    print(data)
    time.sleep(0.2)

if __name__ == '__main__':
    #创建子进程,改变全局变量
    add_process = multiprocessing.Process(target=add_data,name="add_data")
    add_process.start()
    #创建子进程,读取全局变量
    read_process = multiprocessing.Process(target=read_data,name="read_data")
    read_process.start()

10、主进程会等待所有的子进程执行结束再结束

解决方式:

1.子进程设置为守护主进程,这样主进程退出,子进程就销毁。

2.让主进程退出之前先让子进程销毁

子进程守护主进程:sub_process.daemon = True

#-*-coding:utf-8-*-
#主进程要等待子进程执行结束后再结束

#为了让子进程随着主进程的销毁而结束,有两种方式:
#1.让子进程设置为守护主进程,主进程退出子进程销毁,子进程会依赖主进程
import multiprocessing,time
def proce_func():
    while True:
        print("我是子进程……")
        time.sleep(0.2)

if __name__ == '__main__':
    #创建子进程
    sub_process = multiprocessing.Process(target=proce_func)
    #把子进程设置为守护主进程,以后主进程退出,子进程就销毁
    sub_process.daemon = True
    sub_process.start()
    time.sleep(0.5)
    print("over")
    #最终的结果:子进程运行3次,主进程执行到最后一句代码,就完毕。

主进程退出之前先让子进程销毁:sub_process.terminate()

#-*-coding:utf-8-*-
#主进程要等待子进程执行结束后再结束

#为了让子进程随着主进程的销毁而结束,有两种方式:
#1.让子进程设置为守护主进程,主进程退出子进程销毁,子进程会依赖主进程
import multiprocessing,time
def proce_func():
    while True:
        print("我是子进程……")
        time.sleep(0.2)

if __name__ == '__main__':
    #创建子进程
    sub_process = multiprocessing.Process(target=proce_func)
    sub_process.start()
    time.sleep(0.5)
    # 把主进程退出之前,终止子进程
    sub_process.terminate()
    print("over")
    #最终的结果:子进程运行3次,主进程执行到最后一句代码,就完毕。

二、线程

在python中,进程可以实现多任务的执行,同样线程也可以。

1.线程的概念

线程是进程中执行代码的一个分支,每个执行分支(线程)要想工作执行代码需要cpu进行调度,也就是说线程是cpu调度的基本单位。每个进程至少有一个线程,而这个线程就是我们通常说的主线程

线程的作用:多线程可以完成多任务。

说明:程序启动默认会有一个主线程,程序员自己创建的线程可以称为子线程。

2.使用多线程执行多任务

导入线程模块:import threading

线程类参数说明:Thread([group[,target[,name[,args[,kwargs]]]]])

           group:线程组,目前只能使用None

           target:执行的目标任务名

           args:以元组的方式给执行任务传参

           kwargs:以字典方式给执行任务传参

           name:线程名,一般不作设置,默认Thread-N,N为1递增的整数;

启动线程:start

示例:

# -*-coding:utf-8-*-

#多线程运行多任务
#导入线程模块
import threading,time

def thread001():
    #获取当前线程对象
    current_thread=threading.current_thread()
    for i in range(3):
        print("子线程1",current_thread)
    time.sleep(0.2)
def thread002():
    #获取当前线程对象
    current_thread=threading.current_thread()
    for i in range(3):
        print("子线程2",current_thread)
    time.sleep(0.2)

if __name__ == '__main__':
    print(threading.current_thread())
    #创建子线程1
    thread_001=threading.Thread(target=thread001)
    #启动子线程执行对应的线程
    thread_001.start()
    # 创建子线程2
    thread_002 = threading.Thread(target=thread002)
    # 启动子线程执行对应的线程
    thread_002.start()

3.线程执行带有参数的函数

# -*-coding:utf-8-*-
#线程执行待参数的函数
import threading,time
def show_info(name,age):
    print(name,age)

if __name__ == '__main__':
    #创建子线程,元组形式入参,注意:顺序一致
    sub_thread = threading.Thread(target=show_info,args=("ithing",20))
    sub_thread.start()
    # 创建子线程,字典形式入参,注意名称与函数的参数名称一致
    sub_thread1 =threading.Thread(target=show_info,kwargs={"name":"ithing1","age":18})
    sub_thread1.start()
    # 创建子线程,以元组、字典混合入参
    sub_thread2 = threading.Thread(target=show_info,args=("ithing",), kwargs={"age": 18})
    sub_thread2.start()

4.线程的注意点

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

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

为了克服这点,需要将子线程设置为守护主线程,设置主线程有两种方式:

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

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

举例描述:

解决方式1:线程等待(join)子线程一个运行完毕再运行另一个子线程,避免同时对全局变量进行获取。

解决方式2:互斥锁

互斥锁:对共享数据进行锁定,保证同一时刻只能有一个线程去操作。上锁lock.acquire()与释放锁lock.release()需要一起出现,否则会出现死锁的情况,死锁那么程序就一直停留,不会结束。

 

展开阅读全文
©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值