基础概念
进程
是一个执行中的程序,即将程序装载到内存中,系统为它分配资源的这一过程。进程是操作系统资源分配的基本单位。
每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。
-
- 文本区域存储处理器执行的代码;
- 数据区域存储变量和进程执行期间使用的动态分配的内存;
- 堆栈区域存储着活动过程调用的指令和本地变量。
进程状态
进程与程序
- 程序是指令数据的集合,是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念;
- 程序和进程无一一对应关系,一个程序可由多个进程共用,一个进程在活动中又可顺序地执行若干个程序;
- 进程是一个能独立运行的单位,能与其他进程并发执行,进程是作为资源申请和调度单位存在的;而通常的程序段不能作为一个独立运行的单位。
线程
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
python不管PC有几核,在同一核同一时刻执行的线程只有一个,python是调用系统的原生线程。
线程与进程
- 进程要操作CPU,必须要先创建一个线程,所有在同一个进程里的线程是共享同一块内存空间的;线程共享内存空间,进程的内存是独立的;
- 同一个进程的线程之间可以直接交流,两个进程想通信,必须通过一个中间代理来实现;
- 创建新线程很简单, 创建新进程需要对其父进程进行一次克隆;
- 一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程。
同步与异步
同步:是指一个进程在执行某个请求的时候,若这个请求没有执行完成,那么这个进程将会一直等待下去,直到这个请求执行完毕,才会继续执行下面的请求。
异步:是指一个进程在执行某个请求的时候,如果这个请求没有执行完毕,进程不会等待,而是继续执行下面的请求。
并发与并行
并发:计算机的操作系统通过时间片轮转法等算法调度交替执行不同的任务。
并行:同时执行不同的任务。
多线程
线程调用方式
直接调用
import threading import time def run(*args): # 线程要运行的函数 print('test',args) time.sleep(3) t1 = threading.Thread(target=run, args=('t1',)) t2 = threading.Thread(target=run, args=('t2',)) t1.start() t2.start() print(t1.getName()) # Thread-1 print(t2.getName()) # Thread-2
继承式调用
1 class MyThread(threading.Thread): 2 3 def __init__(self, n ): 4 super(MyThread, self).__init__() 5 self.n = n 6 7 def run(self): # 必须写run函数 8 print(self.n) 9 time.sleep(2) 10 11 t1 = MyThread('t1') 12 t2 = MyThread('t2') 13 t1.start() 14 t2.start() 15 16 print(t1.getName()) 17 print(t2.getName())
线程方法
t.join(n) 表示主线程等待子线程多少时间,n表示主线程等待子线程的超时时间,如果在n时间内子线程未完成,主线程不在等待,执行后面的代码 t.run() 线程被cpu调度后自动执行线程对象的run方法(一般我们无需设置,除非自己定义类调用) t.start() 线程准备就绪,等待CPU调度 t.getName() 获取线程的名称 t.setName() 设置线程的名称 t.name 获取或设置线程的名称 t.is_alive() 判断线程是否为激活状态 t.isAlive() 判断线程是否为激活状态 t.isDaemon() 判断是否为守护线程 t.setDaemon() 是否设置守护线程,True表示主线程不等待子线程全部完成就执行后面的代码,False默认值,标识主线程等待子线程全部执行完后继续执行后面的代码 threading.current_thread() 当前线程详细信息 threading.active_count() 当前活跃线程数 threading.get_ident 获得线程号
threading.enumerate() 当前执行的线程列表
线程执行顺序
主线程启动子线程后,两者之间运行是并行的,默认主线程不会等待子线程运行结束,创建完成后继续往下执行,执行完后等待子线程全部执行完后退出程序。
import threading import time def run(*args): # 线程要运行的函数 print('test',args) time.sleep(3) print(args, 'is done') start_time = time.time() for i in range(3): t = threading.Thread(target=run, args=('t-%s' %i ,)) t.start() print("-------------------------------------------") print('run_time = ', time.time()- start_time) # test ('t-0',) # test ('t-1',) # test ('t-2',) # ------------------------------------------- # run_time = 0.0 # ('t-2',) is done # ('t-1',) is done # ('t-0',) is done
加入join,主线程会等待子线程执行完毕后继续往下执行,如果主线程需要子线程的返回结果,可以使用join。
import threading import time def run(*args): # 线程要运行的函数 print('running',args) time.sleep(3) print(args, 'is done') start_time = time.time() thread_pool = [] for i in range(2): t = threading.Thread(target=run, args=('t-%s' %i ,)) t.start() thread_pool.append(t) for i in thread_pool: i.join() print('------------------------------------------') print('run_time = ', time.time()- start_time) # running ('t-0',) # running ('t-1',) # ('t-1',) is done # ('t-0',) is done # ------------------------------------------ # run_time = 3.0156474113464355
join
join 参数:timeout 有n个设置join的子线程,就等待n倍timeout, 默认一直等待执行完毕
当没有设置守护线程时,主线程等待 N 倍timeout后继续往下执行,主线程执行完毕,子线程依然可以继续执行,执行完毕后退出程序;对于守护线程则是到时间就kill子线程。
1 import threading 2 import time 3 def run(*args): # 线程要运行的函数 4 print('running',args) 5 time.sleep(3) 6 print(args, 'is done') 7 8 start_time = time.time() 9 thread_pool = [] 10 for i in range(5): 11 t = threading.Thread(target=run, args=('t-%s' %i ,)) 12 t.setDaemon(True) 13 t.start() 14 thread_pool.append(t) 15 16 for i in thread_pool: 17 i.join(0.5) # 有n个线程就等待n 倍的timeout 18 19 print('------------------------------------------') 20 21 print('run_time = ', time.time()- start_time) 22 23 # 24 # running ('t-0',) 25 # running ('t-1',) 26 # running ('t-2',) 27 # running ('t-3',) 28 # running ('t-4',) 29 # ------------------------------------------ 30 # run_time = 2.531254768371582 31 # 32 # Process finished with exit code 0