一.概念
1.进程
进程是系统进行资源分配和调度的一个独立单位
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。
2.线程
CPU调度和分派的基本单位
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。
3.协程
协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
二.线程的创建:
(1).方法一:
import _thread
import threading
def fn1(a,b):
print(a,b)
print(threading.current_thread().name)
def create_thread1():
#参数一:在子线程中要执行的函数
#参数二:子线程中的函数需要的参数,注意一定要以元组的形式传参
#使用此种方式创建的线程为守护线程,守护线程的特点是,当主线程结束,守护线程无论执行完毕都会结束
_thread.start_new_thread(fn1,("hello","yes"))
if __name__ == "__main__":
create_thread1()
print(threading.current_thread().name)
#注意此时创建的线程中的代码不会执行,原因是
#主线程执行的速度非常快,主线程执行结束,就直接退出了,因此我们的子线程根本不会被创建
#我们可以让主线程阻塞一段时间可以查看一下效果
#time.sleep(3) #这时候我们就可以查看打印的数据了
【使用此方式创建的线程为守护线程】
守护线程:子线程会随着主线程的结束而结束
(2)方法二:
import threading
def func1(*args):
print(args)
print(threading.current_thread().name)
def create_thread2():
#target:在子线程中要执行的函数
#deamo:是否为守护线程
#name:线程名称
t=threading.Thread(target=func1,deamo=False,name="BIG",args=("hello"))
t.start() #启动线程
if __name__ == "__main__":
create_thread2()
(3)方法三:
import threading
class MyThread(threading.Thread):
def __init__(self):
super().__init__()
#一定要重写此方法,此方法会自动被调用
#里面的子线程
def run(self):
print("mythread",threading.current_thread().name)
def create_thread3():
t = MyThread()
t.start()
if __name__ == "__main__":
create_thread3()
注意:一般情况下使用第二种创建方式比较常用
补充:
实例方法:
isAlive(): 返回线程是否在运行。正在运行指启动后、终止前。
get/setName(name): 获取/设置线程名。
start(): 线程准备就绪,等待CPU调度
is/setDaemon(bool): 获取/设置是后台线程(默认前台线程(False))。(在start之前设置)
#如果是后台线程/守护线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,主线程和后台线程均停止
#如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
join([timeout]): 阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout(可选参数)。