计算机组成、进程与线程
一、计算机组成
1.计算机架构:
计算机硬件→操作系统(linux、windows、unix、mac等)→其他系统软件(设备驱动程序、程序语言和开发环境、数据库等)→应用软件(微信、office、notepad++等)
操作系统是一个用来协调、管理和控制计算机硬件和软件资源的系统程序,位于硬件和应用程序之间,而操作系统内核是一个管理和控制程序,负责管理计算机的所有物理资源,包括文件系统、内存管理、设备管理和进程管理等。
应用程序→系统调用接口→操作系统内核→硬件,应用程序调用系统调用接口,操作系统内核管理硬件
2.计算机硬件组成
计算机硬件系统五大组成部分:
运算器:负责算术与逻辑运算
控制器:负责发送和接收指令,与运算器共同组成中央处理器(CPU)
存储器:存储正在进行程序、将要进行程序的数据及刚处理完的数据
输入设备:用来进行输入的设备,例如键盘、扫描仪
输出设备:用来进行输出的设备,例如显示器、音箱
其中,存储器分为两种
RAM:随机存储器,也叫主存(内存),与CPU直接交换数据,通常作为操作系统或其他正在运行中的程序的临时数据存储媒介,可按需随意取出或存入。随时读写且速度快,这种存储器在断电时将丢失其存储内容,主要用于存储短时间使用的程序。
ROM:只读存储器,一种只能读出事先所存数据的固态半导体存储器,一旦存储就无法修改或删除,不会因为电源关闭而消失
主板:安装了组成计算机的主要电路系统,一般有BIOS芯片、I/O控制芯片、键和面板控制开关接扩充插槽、口、指示灯插接件、主板及插卡的直流电源供电接插件等原件
二、计算机发展历史
参见https://www.cnblogs.com/yuanchenqi/articles/6248025.html
三、进程和线程
1.进程
进程是一个程序在一个数据集上的一次动态执行过程,由程序、数据集、进程控制块三部分组成。数据集是程序在执行过程中需要使用的资源;进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志。
2.线程
线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能。
进程和线程的关系:
①一个程序至少有一个进程,一个进程至少有一个线程。(进程可以理解成线程的容器)
②进程在执行过程中拥有独立的内存单元,而多个线程共享内存从而极大地提高了程序的运行效率。
③线程在执行过程中与进程有区别,每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
④进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器、一组寄存器和栈),但是它可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销一个线程,同一个进程中的多个线程之间可以并发执行。
3.python中的线程
①线程示例
python中使用threading模块中的Thread对象开启duoxiancheng
import threading,time def music(): print('begin to listen music %s'%time.ctime()) time.sleep(3) print('stop listening music %s'%time.ctime()) def game(): print('begin to play game %s'%time.ctime()) time.sleep(5) print('stop playing game %s'%time.ctime()) if __name__ == '__main__': ……
#直接顺序执行函数 if __name__ == '__main__': music() game() print('---ending---%s'%time.ctime()) #执行结果 #begin to listen music Tue Jun 18 09:45:33 2019 #stop listening music Tue Jun 18 09:45:36 2019 #begin to play game Tue Jun 18 09:45:36 2019 #stop playing game Tue Jun 18 09:45:41 2019 #---ending---Tue Jun 18 09:45:41 2019
直接执行函数,则music()的begin打印完等待3秒打印stop,同时game()打印begin,再等待5秒game()打印stop,同时主线程打印ending。
#主线程、t1线程和t2线程同时开始运行 if __name__ == '__main__': t1 = threading.Thread(target=music,) t1.start() t2 = threading.Thread(target=game, ) t2.start() print('I\'m the main threading') #执行结果 #begin to listen music Tue Jun 18 09:47:09 2019 #begin to play game Tue Jun 18 09:47:09 2019 #---ending---Tue Jun 18 09:47:09 2019 #stop listening music Tue Jun 18 09:47:12 2019 #stop playing game Tue Jun 18 09:47:14 2019
如果将music()和game()函数分别以线程形式开启,则整个程序为一个进程,也即一个主线程,t1和t2分别为两个子线程。虽然代码顺序上t1比t2先start(),实际执行时t1、t2的begin和主线程的ending同时打印,等待3秒t1打印stop,再等待2秒t2打印stop。
②线程中的join()
一个子线程如果在start后再设置join,则表示该子线程执行完之后主线程才能执行,对其他子线程无影响。
#t1.join() if __name__ == '__main__': t1 = threading.Thread(target=music, ) t1.start() t2 = threading.Thread(target=game, ) t2.start() t1.join() print('---ending---%s'%time.ctime()) #执行结果 #begin to listen music Tue Jun 18 21:16:59 2019 #begin to play game Tue Jun 18 21:16:59 2019 #stop listening music Tue Jun 18 21:17:02 2019 #---ending---Tue Jun 18 21:17:02 2019 #stop playing game Tue Jun 18 21:17:04 2019
t1执行完后主线程的ending才能执行,则t1和t2的begin先同时打印,等待3秒t1打印stop,同时主线程打印ending,再等待2秒t2打印stop。
#t2.join() if __name__ == '__main__': t1 = threading.Thread(target=music, ) t1.start() t2 = threading.Thread(target=game, ) t2.start() t2.join() print('---ending---%s'%time.ctime()) #执行结果 #begin to listen music Tue Jun 18 21:29:43 2019 #begin to play game Tue Jun 18 21:29:43 2019 #stop listening music Tue Jun 18 21:29:46 2019 #stop playing game Tue Jun 18 21:29:48 2019 #---ending---Tue Jun 18 21:29:48 2019
t2执行完后主线程的ending才能执行,则t1和t2的begin先同时打印,等待3秒t1打印stop,再等待2秒t2打印stop,同时主线程打印ending。
#t1和t2同时join if __name__ == '__main__': t1 = threading.Thread(target=music, ) t1.start() t2 = threading.Thread(target=game, ) t2.start() t1.join() t2.join() print('---ending---%s'%time.ctime()) #执行结果 #begin to listen music Tue Jun 18 21:32:18 2019 #begin to play game Tue Jun 18 21:32:18 2019 #stop listening music Tue Jun 18 21:32:21 2019 #stop playing game Tue Jun 18 21:32:23 2019 #---ending---Tue Jun 18 21:32:23 2019
t1和t2执行后主线程的ending才能执行,则t1和t2的begin先同时打印,等待3秒t1打印stop,再等待2秒t2打印stop,同时主线程打印ending。
③线程中的setDeamon(True)
首先明需确,主线程结束表示主线程中的各个子线程执行完成,并且主线程自身的内容也执行完成。
线程的setDaemon(True)需要在线程start之前设置,表示设置该子线程为主线程的守护线程,主线程(除守护进程)结束前该子线程挂起,主线程(除守护进程)结束后该子线程立即结束不再执行,其他子线程正常执行。
#设置t1为主线程的守护进程 if __name__ == '__main__': t1 = threading.Thread(target=music, ) t1.setDaemon(True) t1.start() t2 = threading.Thread(target=game, ) t2.start() print('---ending---%s'%time.ctime()) #执行结果 #begin to listen music Tue Jun 18 21:45:01 2019 #begin to play game Tue Jun 18 21:45:01 2019 #---ending---Tue Jun 18 21:45:01 2019 #stop listening music Tue Jun 18 21:45:04 2019 #stop playing game Tue Jun 18 21:45:06 2019
t1、t2的begin和主线程的ending同时打印,此时t2线程还未结束因此t1挂起,等待3秒t1打印stop,此时t2线程还未结束因此t1继续挂起,再等待2秒t2打印stop。
#设置t2为守护进程 if __name__ == '__main__': t1 = threading.Thread(target=music, ) t1.start() t2 = threading.Thread(target=game, ) t2.setDaemon(True) t2.start() print('---ending---%s'%time.ctime()) #执行结果 #begin to listen music Tue Jun 18 21:49:15 2019 #begin to play game Tue Jun 18 21:49:15 2019 #---ending---Tue Jun 18 21:49:15 2019 #stop listening music Tue Jun 18 21:49:18 2019
t1、t2的begin和主线程的ending同时打印,此时t1还未结束因此t2挂起,等待3秒t1打印stop,此时除了t2未结束主线程及其中的除子线程已经全部结束,t2的stop部分不再打印。
#同时设置t1和t2为守护进程 if __name__ == '__main__': t1 = threading.Thread(target=music, ) t1.setDaemon(True) t1.start() t2 = threading.Thread(target=game, ) t2.setDaemon(True) t2.start() print('---ending---%s'%time.ctime()) #执行结果 #begin to listen music Tue Jun 18 22:00:38 2019 #begin to play game Tue Jun 18 22:00:38 2019 #---ending---Tue Jun 18 22:00:38 2019
t1、t2的begin和主线程的ending同时打印,此时t1、t2未结束但主线程自身结束,因此t1和t2的stop都不再打印。
④自定义线程类(建议直接实例化,不建议自定义)
自定义线程类需要继承threading的Thread类,并重写run方法,示例如下
class MyThreading(threading.Thread): def __init__(self,num): threading.Thread.__init__(self) self.num = num def run(self): print('i\'m threading %s'%self.num) if __name__ == '__main__': t1 = MyThreading(2) t1.start() t2 = MyThreading(5) t2.start() print('-- ending---')
⑤线程中其他方法
线程实例的方法
getName()和setName('name'): 获取和设置线程名
isAlive(): 返回线程是否为存活状态
例如上述例子中t1.getName()为获取t1子线程的名称,形式为Thread-n(n为正整数),可以根据功能自省设定线程名称,
run(): 线程被cpu调度后自动执行线程对象的run方法
start():启动线程活动
Thread模块中提供的方法
threading.current_thread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.active_count(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。