首页 > 代码库 > 进程与线程
进程与线程
操作系统
1.为什么要有操作系统
操作系统,位于底层硬件与应用软件之间的一层
工作方式:向下管理硬件,向上提供接口
操作系统进程切换:
1.出现IO操作
2.固定时间
进程
1.定义
进程就是一个程序在一个数据集上的一次动态执行过程。进程一般由程序、数据集、进程控制块三部分组成。我们编写的程序用来描述进程要完成哪些功能以及如何完成;数据集则是程序在执行过程中所需要使用的资源;进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志。
进程由三部分组成:
1、程序:我们编写的程序用来描述进程要完成哪些功能以及如何完成
2、数据集:数据集则是程序在执行过程中所需要使用的资源
3、进程控制块:进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感
知进程存在的唯一标志。
线程
线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干一样事的缺陷,使到进程内并发成为可能。线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能。线程没有自己的系统资源。
Threading用于提供线程相关的操作。线程是应用程序中工作的最小单元,它被包含在进程之中,是进程中的实际运作单位。一
条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
进程与线程的关系
进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。或者说进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
线程则是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
进程和线程的关系:
(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源。
(3)CPU分给线程,即真正在CPU上运行的是线程。
进程: 资源管理单位(容器)
线程: 最小执行单位
并行与并发
并行处理(Parallel Processing)是计算机系统中能同时执行两个或更多个处理的一种计算方法。并行处理可同时工作于同一程序的不同方面。并行处理的主要目的是节省大型和复杂问题的解决时间。并发处理(concurrency Processing):指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机(CPU)上运行,但任一个时刻点上只有一个程序在处理机(CPU)上运行
并发的关键是你有处理多个任务的能力,不一定要同时。并行的关键是你有同时处理多个任务的能力。所以说,并行是并发的子集
同步与异步
在计算机领域,同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。举个例子,打电话时就是同步通信,发短息时就是异步通信。
1. 实现线程并发
示例1:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading #线程 6 import time 7 8 def Hi(num): #有一个参数 9 print("hello %s" %num)10 time.sleep(3) 11 12 if __name__ == ‘__main__‘:13 14 t1=threading.Thread(target=Hi,args=(10,)) #创建了一个线程对象t1,10做为一个参数,传给num15 t1.start()16 17 t2=threading.Thread(target=Hi,args=(9,)) #创建了一个线程对象t2,9做为一个参数,传给num18 t2.start()19 20 print("ending.........") #主线程输出ending
执行结果:
1 hello 10 #子线程2 hello 9 #子线程3 ending......... #主线程4 #上面三个同时出来,再停顿三秒才结束5 Process finished with exit code 0 #停顿3秒才结束
示例2:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 import time 7 8 def music(): 9 print("begin to listen %s"%time.ctime())10 time.sleep(3)11 print("stop to listen %s" %time.ctime())12 13 def game():14 print("begin to play game %s"%time.ctime())15 time.sleep(5)16 print("stop to play game %s" %time.ctime())17 18 if __name__ == ‘__main__‘:19 20 t1=threading.Thread(target=music)21 t1.start()22 t2=threading.Thread(target=game)23 t2.start()
执行结果:
1 #总共花了5秒时间2 3 begin to listen Sat Jan 14 12:34:43 20174 begin to play game Sat Jan 14 12:34:43 2017 #1、先打印2个5 6 stop to listen Sat Jan 14 12:34:46 2017 #2、等待3秒再打印一个7 8 stop to play game Sat Jan 14 12:34:48 2017 #3、再等待2秒,打印一个
2.使用 join方法
示例1:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 import time 7 8 def music(): 9 print("begin to listen %s"%time.ctime())10 time.sleep(3)11 print("stop to listen %s" %time.ctime())12 13 def game():14 print("begin to play game %s"%time.ctime())15 time.sleep(5)16 print("stop to play game %s" %time.ctime())17 18 if __name__ == ‘__main__‘:19 20 t1=threading.Thread(target=music)21 t2=threading.Thread(target=game)22 23 t1.start() #运行实例的方法24 t2.start()25 26 t1.join() #子线程对象调用join()方法27 t2.join()28 29 print("ending") #在主线程中
执行结果:
1 begin to listen Sat Jan 14 12:58:34 20172 begin to play game Sat Jan 14 12:58:34 2017 #先打印2个3 4 stop to listen Sat Jan 14 12:58:37 2017 #等待3秒,再打印一个5 6 stop to play game Sat Jan 14 12:58:39 2017 #等待2秒,再打印两个7 ending
示例2:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 import time 7 8 def music(): 9 print("begin to listen %s"%time.ctime())10 time.sleep(3)11 print("stop to listen %s" %time.ctime())12 13 def game():14 print("begin to play game %s"%time.ctime())15 time.sleep(5)16 print("stop to play game %s" %time.ctime())17 18 if __name__ == ‘__main__‘:19 20 t1=threading.Thread(target=music)21 t2=threading.Thread(target=game)22 23 t1.start() #运行实例的方法24 t2.start()25 26 t1.join() #t1线程不结束,谁都不往下走27 28 print("ending")
执行结果:
1 begin to listen Sat Jan 14 13:06:07 20172 begin to play game Sat Jan 14 13:06:07 2017 #先打印这两行3 4 stop to listen Sat Jan 14 13:06:10 2017 #再等待3秒打印这两行5 ending6 7 stop to play game Sat Jan 14 13:06:12 2017 #再等待2秒打印这行
示例3:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 import time 7 8 def music(): 9 print("begin to listen %s"%time.ctime())10 time.sleep(3)11 print("stop to listen %s" %time.ctime())12 13 def game():14 print("begin to play game %s"%time.ctime())15 time.sleep(5)16 print("stop to play game %s" %time.ctime())17 18 if __name__ == ‘__main__‘:19 20 t1=threading.Thread(target=music)21 t2=threading.Thread(target=game)22 23 t1.start() #运行实例的方法24 t2.start()25 26 t2.join()27 28 print("ending") #在主线程中
执行结果:
1 begin to listen Sat Jan 14 13:12:34 2017 #先打印这两行2 begin to play game Sat Jan 14 13:12:34 20173 4 stop to listen Sat Jan 14 13:12:37 2017 #等待3秒,打印这一行5 6 stop to play game Sat Jan 14 13:12:39 2017 #等待2秒,打印这两行7 ending
示例4: 并没有实现并发(实现多线程的意义)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 import time 7 8 def music(): 9 print("begin to listen %s"%time.ctime())10 time.sleep(3)11 print("stop to listen %s" %time.ctime())12 13 def game():14 print("begin to play game %s"%time.ctime())15 time.sleep(5)16 print("stop to play game %s" %time.ctime())17 18 if __name__ == ‘__main__‘:19 20 t1=threading.Thread(target=music)21 t2=threading.Thread(target=game)22 23 t1.start()24 25 t1.join()26 t2.start()27 28 t2.join()29 30 print("ending") #在主线程中
执行结果:
1 begin to listen Sat Jan 14 13:26:18 2017 #先打印条1行2 3 stop to listen Sat Jan 14 13:26:21 2017 #等待3秒再打印2行4 begin to play game Sat Jan 14 13:26:21 20175 6 stop to play game Sat Jan 14 13:26:26 2017 #等待5秒打印2行7 ending
线程调用方法:
1.直接调用
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 import time 7 8 9 def sayhi(num): # 定义每个线程要运行的函数10 11 print("running on number:%s" % num)12 13 time.sleep(3)14 15 16 if __name__ == ‘__main__‘:17 t1 = threading.Thread(target=sayhi, args=(1,)) # 生成一个线程实例18 t2 = threading.Thread(target=sayhi, args=(2,)) # 生成另一个线程实例19 20 t1.start() # 启动线程21 t2.start() # 启动另一个线程22 23 print(t1.getName()) # 获取线程名24 print(t2.getName())
执行结果:
1 running on number:12 running on number:23 Thread-14 Thread-2
2.继承式调用
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 import time 7 8 #自己定制一个MyThread的类 9 class MyThread(threading.Thread): 10 def __init__(self, num):11 threading.Thread.__init__(self)12 self.num = num13 14 def run(self): # 定义每个线程要运行的函数15 16 print("running on number:%s" % self.num)17 18 time.sleep(3)19 20 21 if __name__ == ‘__main__‘:22 t1 = MyThread(1) #继承这个类,把1这个参数,传给num ,t1就是个线程对象23 t2 = MyThread(2)24 t1.start()25 t2.start()26 27 print("ending......")
执行结果:
1 running on number:12 running on number:23 ending......
用Daemon方法示例(设置t为守护线程,就是字线程,跟着主线程一起推出)
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 from time import ctime,sleep 7 import time 8 9 def ListenMusic(name):10 11 print ("Begin listening to %s. %s" %(name,ctime()))12 sleep(3)13 print("end listening %s"%ctime())14 15 def RecordBlog(title):16 17 print ("Begin recording the %s! %s" %(title,ctime()))18 sleep(5)19 print(‘end recording %s‘%ctime())20 21 #创建一个列表,把t1和t2加到列表中去22 threads = []23 t1 = threading.Thread(target=ListenMusic,args=(‘水手‘,))24 t2 = threading.Thread(target=RecordBlog,args=(‘python线程‘,))25 threads.append(t1)26 threads.append(t2)27 28 if __name__ == ‘__main__‘:29 30 for t in threads:31 t.setDaemon(True) #设置t为守护线程; 注意:一定在start()之前设置,否则会报错32 33 t.start()34 35 print ("all over %s" %ctime())
执行结果:
1 Begin listening to 水手. Sat Jan 14 13:51:30 2017 #三个同时打印出来2 Begin recording the python线程! Sat Jan 14 13:51:30 20173 all over Sat Jan 14 13:51:30 2017
示例3: 设置t1为守护线程,没有意义,达不到效果,因为t2还会继续执行
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 from time import ctime,sleep 7 import time 8 9 def ListenMusic(name):10 11 print ("Begin listening to %s. %s" %(name,ctime()))12 sleep(3)13 print("end listening %s"%ctime())14 15 def RecordBlog(title):16 17 print ("Begin recording the %s! %s" %(title,ctime()))18 sleep(5)19 print(‘end recording %s‘%ctime())20 21 #创建一个列表,把t1和t2加到列表中去22 threads = []23 t1 = threading.Thread(target=ListenMusic,args=(‘水手‘,))24 t2 = threading.Thread(target=RecordBlog,args=(‘python线程‘,))25 threads.append(t1)26 threads.append(t2)27 28 if __name__ == ‘__main__‘:29 30 t1.setDaemon(True) #设置t1为守护线程; 注意:一定在start之前设置,否则会报错31 for t in threads:32 33 t.start()34 35 print ("all over %s" %ctime())
执行结果:
1 Begin listening to 水手. Sat Jan 14 14:02:07 20172 Begin recording the python线程! Sat Jan 14 14:02:07 20173 all over Sat Jan 14 14:02:07 2017 #设置t1为守护线程,所以会先把这三条先打印出来4 5 end listening Sat Jan 14 14:02:10 2017 #再等待3秒打印t2,6 7 end recording Sat Jan 14 14:02:12 2017 #再等待3秒打印这条出来
示例4:设置t2为守护线程,子线程才会跟着主线程一起退出
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 from time import ctime,sleep 7 import time 8 9 def ListenMusic(name):10 11 print ("Begin listening to %s. %s" %(name,ctime()))12 sleep(3)13 print("end listening %s"%ctime())14 15 def RecordBlog(title):16 17 print ("Begin recording the %s! %s" %(title,ctime()))18 sleep(5)19 print(‘end recording %s‘%ctime())20 21 #创建一个列表,把t1和t2加到列表中去22 threads = []23 t1 = threading.Thread(target=ListenMusic,args=(‘水手‘,))24 t2 = threading.Thread(target=RecordBlog,args=(‘python线程‘,))25 threads.append(t1)26 threads.append(t2)27 28 if __name__ == ‘__main__‘:29 30 t2.setDaemon(True) # 设置t2为守护线程; 注意:一定在start之前设置,否则会报错31 for t in threads:32 33 t.start()34 35 print ("all over %s" %ctime())
执行结果:
1 Begin listening to 水手. Sat Jan 14 14:17:09 20172 Begin recording the python线程! Sat Jan 14 14:17:09 20173 all over Sat Jan 14 14:17:09 2017 #先打印这三条4 5 end listening Sat Jan 14 14:17:12 2017 #等待3秒,再打印这条;t1结束后,主线程也结束了。
其他方法:
Thread实例对象的方法
# isAlive(): 返回线程是否活动的。 # getName(): 返回线程名。 # setName(): 设置线程名。threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程变量。 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 5 import threading 6 from time import ctime,sleep 7 import time 8 9 def ListenMusic(name):10 11 print ("Begin listening to %s. %s" %(name,ctime()))12 sleep(3)13 print("end listening %s"%ctime())14 15 def RecordBlog(title):16 17 print ("Begin recording the %s! %s" %(title,ctime()))18 sleep(5)19 print(‘end recording %s‘%ctime())20 21 #创建一个列表,把t1和t2加到列表中去22 threads = []23 t1 = threading.Thread(target=ListenMusic,args=(‘水手‘,))24 t2 = threading.Thread(target=RecordBlog,args=(‘python线程‘,))25 threads.append(t1)26 threads.append(t2)27 28 if __name__ == ‘__main__‘:29 30 t2.setDaemon(True) # 设置t为守护进程; 注意:一定在start之前设置,否则会报错31 for t in threads:32 t.start()33 print(t.getName()) #返回线程名称:Thread-134 35 print ("all over %s" %ctime())
GIL(全局解释器锁)
无论你启多少个线程,你有多少个cpu, Python在执行的时候会淡定的在同一时刻只允许一个线程运行。
进程与线程