第1章
进程和线程
6小时13分钟53节
1-1
进程和线程的概述进程就是运行中的应用程序。应用程序是静态的,进程是动态的。查看所有正在运行的进程,每个进程至少对应一个线程。每个进程都用来完成一件任务,每个线程用来完成进程内的一件子任务。线程就是进程内部的一个执行单元。每个进程都有独立的内存空间,而进程内的所有线程共享内存空间。不管是单核CPU还是多核CPU,都支持多任务。多个任务交替执行的方式称为并发。多个任务同时执行的方式称为并行。
「仅限付费用户」点击下载“01_01进程和线程的概述.zip”
[11:18]
开始学习
1-2
自动创建与启动的进程当在PyCharm中运行一个py文件时,PyCharm对应的进程会自动创建并启动一个新进程,其默认名称为Python。当py文件运行结束时,自动创建并启动的新进程也随之结束。创建并启动子进程的进程被称为父进程。
「仅限付费用户」点击下载“01_02自动创建与启动的进程.zip”
[07:54]
开始学习
1-3
子进程的创建与启动之直接实例化Process(上)标准库模块multiprocessing中提供了一个类对象Process,用于表示进程。使用类对象Process创建并启动子进程的第1种方式为:(1)根据类对象Process创建进程实例对象;(2)调用进程实例对象的方法start()启动进程。调用方法start()后,会自动调用方法run(),方法run()会自动调用参数target指定的函数。
「仅限付费用户」点击下载“01_03子进程的创建与启动之直接实例化Process(上).zip”
[09:41]
开始学习
1-4
子进程的创建与启动之直接实例化Process(下)调用特殊方法__init__()时必须指定关键字实参,其中:(1)参数group用于指定进程实例对象所属的进程组,默认不属于任何进程组。(2)参数target用于指定被方法run()调用的函数,默认没有函数被调用。(3)参数name用于指定进程实例对象的名称,第n个子进程的默认名称为'Process-n'。此外,可以通过属性name设置进程实例对象的名称。(4)参数args用于指定target接收的位置参数,用元组表示,默认不接收位置参数。(5)参数kwargs用于指定target接收的关键字参数,用字典表示,默认不接收关键字参数。
「仅限付费用户」点击下载“01_04子进程的创建与启动之直接实例化Process(下).zip”
[06:14]
开始学习
1-5
子进程的创建与启动之继承Process使用类对象Process创建并启动子进程的第2种方式为:(1)自定义继承自Process的类对象,重写特殊方法__init__()和方法run();(2)根据自定义的类对象创建进程实例对象;(3)调用进程实例对象的方法start()启动进程。调用方法start()后,会自动调用重写后的方法run()。与第1种方式相比,相当于把参数target指定的函数的函数体转移到了方法run()中。因此,在创建进程实例对象时无需再指定参数target。第1种方式创建进程实例对象时指定的其它参数,在第2种方式中可以传递给重写后的特殊方法__init__()。
「仅限付费用户」点击下载“01_05子进程的创建与启动之继承Process.zip”
[12:09]
开始学习
1-6
子进程的创建与启动之调用函数fork()标准库模块os中提供了一个函数fork(),用于将当前进程复制一份子进程,而后父进程和子进程从调用fork()处开始分叉(fork的含义),兵分两路,继续并行运行后面的程序。与普通函数不同的是,函数fork()会返回两次,分别在父进程和子进程内返回。返回值有三种情况:(1)返回值小于0,表示复制子进程失败;(2)返回值为0,表示处在子进程中;(3)返回值大于0,表示处在父进程中,返回值就是子进程的id。在Windows操作系统上无法调用函数fork(),因为函数fork()不是跨平台的。而模块multiprocessing是跨平台的。
「仅限付费用户」点击下载“01_06子进程的创建与启动之调用函数fork().zip”
[09:12]
开始学习
1-7
自动创建与启动的父线程任何进程都会自动创建并启动一个线程,该线程被称为父(主)线程。父(主)线程的默认名称是MainThread。
「仅限付费用户」点击下载“01_07自动创建与启动的父线程.zip”
[07:26]
开始学习
1-8
子线程的创建与启动之直接实例化Thread标准库模块threading中提供了一个类对象Thread,用于表示线程。使用类对象Thread创建并启动子线程的第1种方式为:(1)根据类对象Thread创建线程实例对象;(2)调用线程实例对象的方法start()启动线程。调用方法start()后,会自动调用方法run(),方法run()会自动调用参数target指定的函数。
「仅限付费用户」点击下载“01_08子线程的创建与启动之直接实例化Thread.zip”
[08:13]
开始学习
1-9
子线程的创建与启动之继承Thread使用类对象Thread创建并启动子线程的第2种方式为:(1)自定义继承自Thread的类对象,重写特殊方法__init__()和方法run();(2)根据自定义的类对象创建线程实例对象;(3)调用线程实例对象的方法start()启动线程。调用方法start()后,会自动调用重写后的方法run()。与第1种方式相比,相当于把参数target指定的函数的函数体转移到了方法run()中。因此,在创建线程实例对象时无需再指定参数target。第1种方式创建线程实例对象时指定的其它参数,在第2种方式中可以传递给重写后的特殊方法__init__()。
「仅限付费用户」点击下载“01_09子线程的创建与启动之继承Thread.zip”
[06:12]
开始学习
1-10
多进程执行的不确定性默认情况下,多个进程的执行顺序和时间都是不确定的,完全取决于操作系统的调度。
「仅限付费用户」点击下载“01_10多进程执行的不确定性.zip”
[05:31]
开始学习
1-11
多线程执行的不确定性默认情况下,进程内所有线程的执行顺序和时间都是不确定的,完全取决于操作系统的调度。
「仅限付费用户」点击下载“01_11多线程执行的不确定性.zip”
[02:56]
开始学习
1-12
守护父进程的子进程可以在调用进程实例对象的方法start()之前将属性daemon的值设置为True,从而将该进程设置为守护进程。守护进程是为了守护父进程而存在的子进程。当父进程结束时,守护进程就没有存在的意义了,因此,守护进程会随着父进程的结束而立刻结束。
「仅限付费用户」点击下载“01_12守护父进程的子进程.zip”
[06:11]
开始学习
1-13
守护父线程的子线程在创建线程实例对象时,可以将参数daemon指定为True,从而将创建的线程设置为守护线程。此外,也可以在调用方法start()之前调用线程实例对象的方法setDaemon(True)或将属性daemon的值设置为True,从而将该线程设置为守护线程。守护线程是为了守护父线程而存在的子线程。当父线程结束时,守护线程就没有存在的意义了,因此,守护线程会随着父线程的结束而立刻结束。
「仅限付费用户」点击下载“01_13守护父线程的子线程.zip”
[05:17]
开始学习
1-14
阻塞父进程的子进程之方法join()在父进程中创建并启动子进程后,可以调用子进程的方法join(),这样,子进程会把父进程阻塞,父进程会等子进程执行完之后再从被阻塞的地方继续执行。在调用方法join()时,可以指定参数timeout,从而指定子进程阻塞父进程的时间。
「仅限付费用户」点击下载“01_14阻塞父进程的子进程之方法join().zip”
[08:23]
开始学习
1-15
阻塞父线程的子线程之方法join()在父线程中创建并启动子线程后,可以调用子线程的方法join(),这样,子线程会把父线程阻塞,父线程会等子线程执行完之后再从被阻塞的地方继续执行。在调用方法join()时,可以指定参数timeout,从而指定子线程阻塞父线程的时间。
「仅限付费用户」点击下载“01_15阻塞父线程的子线程之方法join().zip”
[03:38]
开始学习
1-16
进程池Pool如果并发的任务数过多,一次性创建并启动大量的进程会给计算机带来很大的压力,那么就可以使用进程池对创建与启动的进程进行限制和管理。进程池中所能容纳的进程数目是固定的。标准库模块multiprocessing中提供了一个类对象Pool,用于表示进程池。进程池中所能容纳的进程数目可以在创建Pool实例对象时进行指定;如果不指定,默认大小是CPU的核数。
「仅限付费用户」点击下载“01_16进程池Pool.zip”
[12:51]
开始学习
1-17
线程池ThreadPool如果并发的任务数过多,一次性创建与启动大量的线程会给计算机带来很大的压力,那么就可以使用线程池对创建与启动的线程进行限制和管理。线程池中所能容纳的线程数目是固定的。当需要创建与启动一个子线程时,如果线程池还没满,则会创建与启动一个子线程并添加到线程池中;如果线程池已经满了,则会一直等待,直到线程池中有任意一个子线程结束从而腾出一个位置,才会创建与启动一个子线程并添加到线程池中。第三方库threadpool中提供了一个类对象ThreadPool,用于表示线程池。线程池中所能容纳的线程数目可以在创建ThreadPool实例对象时进行指定。
「仅限付费用户」点击下载“01_17线程池ThreadPool.zip”
[07:54]
开始学习
1-18
进程池ProcessPoolExecutor(上)标准库模块concurrent.futures中提供了一个类对象ProcessPoolExecutor,也用于表示进程池。与Pool相比,ProcessPoolExecutor的功能和性能更加强大。类对象ProcessPoolExecutor遵守了上下文管理协议,所以可以使用with语句,这样,在离开运行时上下文时会自动调用方法shutdown(wait=True)。
「仅限付费用户」点击下载“01_18进程池ProcessPoolExecutor(上).zip”
[10:48]
开始学习
1-19
进程池ProcessPoolExecutor(中)方法submit()的返回值是一个Future实例对象,表示子进程所调用的那个函数的执行(比如:do_sth())。可以调用Future的方法result()得到这个函数的返回值。方法result()是一个同步方法,也就是说,直到这个函数执行完毕之后方法result()才会返回。
「仅限付费用户」点击下载“01_19进程池ProcessPoolExecutor(中).zip”
[06:40]
开始学习
1-20
进程池ProcessPoolExecutor(下)标准库模块concurrent.futures中还提供了两个函数:(1)wait(fs, timeout=None, return_when=ALL_COMPLETED),该函数用于阻塞父进程,以等待指定的Future实例对象序列,直到满足指定的条件。(2)as_completed(fs, timeout=None),该函数用于将指定的Future实例对象序列转换为一个迭代器,当序列中的任意一个Future实例对象已经完成或已被取消时都会被yield。这样,通过遍历得到的迭代器,就可以在任意一个Future实例对象已经完成或已被取消时立即做一些处理,比如调用方法result()得到执行结果。
「仅限付费用户」点击下载“01_20进程池ProcessPoolExecutor(下).zip”
[15:00]
开始学习