进程
(Process)是对计算机中程序的一次运行过程的描述。编写完毕的代码,在没有运行的时候,成为程序;正在运行着的代码,在这个运行过程就称为进程。
对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。
有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。
由于每个进程至少要干一件事,所以,一个进程至少有一个线程
。当然,像Word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。当然,真正地同时执行多线程需要多核CPU才可能实现。
线程是最小的执行单元,而进程由至少一个线程组成。如何调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间。
在一个程序中实现多任务处理,可以使用多线程和多进程两种方式
多进程
多进程创建:使用Process类,每次实例化这个类的时候,就创建一个进程对象。
多进程:一个程序运行过程中,产生了多个进程
1.n个正在运行的程序—至少n个进程
2.1个程序-----可能只有一个进程,也可能有多个进程
#引入进程类
from multiprocessing import Process
import time
#任务1
def run1():
print("执行了任务1!")
time.sleep(5)
#任务2
def run2():
print("执行了任务2!")
time.sleep(5)
#任务3
def run3():
print("执行了任务3!")
time.sleep(5)
#------------------------串行
# run1()
# run2()
# run3()
#------------------------并行
#创建进程对象
p1=Process(target=run1) #(target=要执行的任务方法)
p2=Process(target=run2)
p3=Process(target=run3)
if __name__=='__main__':
p1.start()#启动进程,只能写到main中
p2.start()
p3.start()
启动进程,只能写到main
中
执行了任务1!
执行了任务2!
执行了任务3!
多线程
- 线程是CPU调度的基本单位,是进程中具体的执行单元;
- 进程包含线程,一个进程中至少包含一个线程;
- 如果一个进程中包含了多个线程,称为多线程。
多线程的实现:
1.引入threading模块 | |
---|---|
2.创建线程对象 | |
3. 启动线程 |
import threading
import time
def run(name):
print("执行了任务!")
time.sleep(5)
#--创建线程对象
t1=threading.Thread(target=run,args=("t1",))
t2=threading.Thread(target=run,args=("t2",))
t3=threading.Thread(target=run,args=("t3",))
#启动线程
t1.start()
t2.start()
t3.start()
#多进程切换消耗的CPU资源较多
执行了任务!
执行了任务!
执行了任务!
主线程和子线程
程序执行时,程序本身就是一个线程,称为主线程
手动创建的线程,称为子线程
主线程执行中不会等待子线程执行完毕,会直接执行后面代码
import threading
import time
def run(name):
print("执行了任务!")
time.sleep(5)
#--创建线程对象
t1=threading.Thread(target=run,args=("t1",))
t2=threading.Thread(target=run,args=("t2",))
t3=threading.Thread(target=run,args=("t3",))
#启动线程
t1.start()
t2.start()
t3.start()
t1.join()#需要等待当前线程执行完毕,才能继续执行主线程
t2.join()
t3.join()
print("执行完毕!")
执行了任务!
执行了任务!
执行了任务!
执行完毕!
join
方法可使当前线程执行完毕后继续执行主线程
线程锁
当一个线程设置锁后,只有等到释放锁后,才能调度其他线程
import threading
num=100
def run(name):
global num
num-=1
print("线程",name,"执行了,目前num的值为:",num)
for i in range(1,101):
t=threading.Thread(target=run,args=(i,))
t.start()
若不使用线程锁,则运行结果可能会出现错乱
线程 1 执行了,目前num的值为: 99
线程 2 执行了,目前num的值为: 98
线程 3 执行了,目前num的值为: 97
线程 4 执行了,目前num的值为: 线程 5 执行了,目前num的值为:96
95
线程 6 执行了,目前num的值为: 94
········
线程 100 执行了,目前num的值为: 0
- 使用线程锁
import threading
# 线程锁(互斥锁):当一个线程设置锁后,只有等到释放锁后,才能调度其他线程
lock=threading.Lock()#创建锁
num=100
def run(name):
global num
num-=1
print("线程",name,"执行了,目前num的值为:",num)
for i in range(1,101):
t=threading.Thread(target=run,args=(i,))
t.start()
此时将不会发生错乱
案例
多线程聊天室
from threading import Thread
from socket import *
#接收信息
def recvData():
msg=s.recv(1024)
print(">>:",msg.decode())
#发送信息
def sendData():
info=input("<<:")
s.sendto(info.encode(),(ip,port))
#--------------------
ip="localhost"#对方ip
port=9001#对方端口号
s=socket(AF_INET,SOCK_DGRAM)
s.bind(("localhost",9002))
tr=Thread(target=recvData)
ts=Thread(target=recvData)
tr.start()
ts.start()