1.什么是多任务?
通俗化:当一个程序运行起来,既可以干这个也可以干那个。(如;音乐:听歌的同时,聊微信)
2.多任务、单核cpu、多核cpu、并发、并行
单核cpu实现多任务的原理:时间片轮转
- 单核CPU同一时间只能运行一个程序,但是为什么你能感觉同时运行了好多个程序?
因为单核cpu的快速切换,即把一个程序拿过来运行极短的时间比如0.00001秒,就换运行下一个程序,如此往复,就是你看到的同一时间执行多个程序。这是操作系统实现多任务的一种方式,但其实是伪多任务。 - 时间片轮转的理念:利用人眼看到时间与程序运行的时间的偏差,通过快速切换程序,瞒过眼睛,区别不出来切换了程序。
并行、并发
如果是多核cpu同时运行多个任务,我们就称之为并行,是真的多任务;任务数少于cpu数量;
如果是单核cpu切换着运行多个任务,我们就称之为并发,是假的多任务。任务数多于cpu数量;
但因为日常中,任务数一般多于cpu核数,所以我们说的多任务一般都是并发,即假的多任务;
多任务之进程
- 什么是进程?
程序运行,资源分配的单位 - 用进程如何实现多任务?
1. 导入multiprocessing;
2. 编写多任务所所需要的函数;
3. 创建multiprocessing.Process类的实例对象并传入函数引用;
4. 调用实例对象的start方法,创建子进程。
test1、test2同时执行
import multiprocessing ,time
def test1():
for i in range(10):
time.sleep(1)
print i
def test2():
for i in range(10):
time.sleep(1)
print ('test %d' %i)
print ('test start')
process1 = multiprocessing.Process(target= test1)
process2 = multiprocessing.Process(target= test2)
process1.start() #启动子进程时,复制了一份主进程的所有资源和代码
process2.start()
通过 在cmd命令行 : ps -aux 可以看到有3个进程(其中1个是主进程,2个子进程)
进程剖析:
- 主进程有什么,子进程就会有什么资源;
- 线程能创建多任务,进程也能创建多任务,但进程耗费的资源比较大;所以运行的进程数,不一定越多越好;
- 当创建子进程时,会复制一份主进程的资源,代码,内存等,但又会有自己不同的地方,比如pid等;
- 我们可以理解为多进程之间共享代码,即只有一份代码,但有多个指向同一代码的箭头;能共享的就共享,不能共享的就拷贝一份;不需要修改的就共享,要修改的时候就给你拷贝一份,这就是写时拷贝
多任务之线程
- 什么是线程?
操作系统调度的单位 - 多线程实现多任务
1.导入threading模块;
2.编写多任务所需要的的函数;
3.创建threading.Thread类的实例对象并传入函数引用;
4.调用实例对象的start方法,创建子线程。
核心
import threading
th = threading.Thread(target = function_Name)
th.start()
注意:
①一个Thread实例对象只能有一个线程
关于target = function_Name : 只能写函数名,不能写function_Name(),
* 函数名() 表示函数的调用
* 函数名 表示使用对函数的引用,告诉函数在哪,即指向该函数;
知识点:变量q= 函数名 -------变量q指向该函数
②关于th.start() : 运行start(),即自动创建一个子线程
import threading ,time
def test1():
for i in range(10):
time.sleep(1)
print i
def test2():
for i in range(10):
time.sleep(1)
print ('test %d' %i)
thread1 = threading.Thread(target= test1)
thread2 = threading.Thread(target= test2)
thread1.start()
thread2.start()
-
主线程和子线程
当程序运行代码起来---------这个是主线程,只有一个主线程
当代码运行到start()函数时-------会自动创建一个子线程 -
如何确定线程的执行顺序?
因线程的运行是没有顺序的,随机的。可通过延时time.sleep(),让线程谁先执行,谁后执行。 -
子线程何时结束?
当创建Thread时执行的那个函数,该函数运行完,意味着该子线程结束
6.给子线程传参
g_num = [1,3]
threading.Thread(target = function_Name, args=(g_num,)) #args 是个元组
7.通过继承Thread类来创建线程
前面我们是通过子线程调用一个函数,那么当函数过多时,想将那些函数封装成一个类,我们可以不可以通过子线程调用一个类呢?
1.导入threading模块
2.定义一个继承threading.Thread的类,并该类中定义一个run()函数
3.创建该类的实例对象
4.实例对象调用start()函数
注意:
Thread类的start()函数,就是调用Thread类中的run()
import threading ,time
class Test(threading.Thread):
def test1(self):
for i in range(10):
time.sleep(1)
print i
def test2(self):
for i in range(10):
time.sleep(1)
print ('test %d' %i)
def run(self):
self.test1()
self.test2()
test = Test()
test.start()