什么是进程:
进程是程序的一次动态执行过程,每个进程度拥有自己的地址空间、内存、数据栈一技其他用于跟踪执行的辅助数据
操作系统负责其上所有的进程的执行,操作系统会位这个进程合理的分配执行时间
什么是线程:
线程是操作系统能够进行运算的调度的最小单位,它被包含在进程之中,是进程中的实际运作单位
一个线程只得是进程中一个单一的控制流,一个进程中可以并发多个线程,每条线程执行不同的任务
一个线程是一个execution context(执行上下文),即一个cpu执行时所需要的一串指令
主线程:
线程就是创建进程的第一个线程,也就是main函数对应的线程
创建线程
需要导入threading模块
from threading import Thread
t3 = Thread(target=task3) #创建一个线程对象
线程中的方法:
run() # 运行线程,仅仅是普通函数调用,如果使用run方法启动线程,无法达到多线程的目的
start() # 执行开始线程
join() # 线程阻塞,执行完当前线程才执行后面的
name 查看线程名,默认的线程名Thread-1,第二个Thread-2…
is_alive() # 判断当前线程是否存活
在线程中,如果有全局变量是每个线程之间共享,这样就有一个问题:就是可能我不同的线程在重复处理一件事,所有需要使用线程锁
线程创建的代码示例
# encoding: utf-8
from threading import Thread, current_thread, Lock
def task3():
for i in range(5):
print("正在进行task3函数的第{}次任务".format(i), os.getpid(), os.getppid())
time.sleep(0.5)
def task4(n):
for i in range(n):
print("正在进行task4函数的第{}次任务".format(i), os.getpid(), os.getppid())
time.sleep(0.5)
if __name__ == '__main__':
t3 = Thread(target=task3, name="task3") # 创建线程对象,name配置线程名
t4 = Thread(target=task4, args=(6, ))
t3.start() # 启动线程
t4.start()
print(t3.is_alive()) # 判断线程是否存活
print(t4.is_alive())
t3.join() # 阻塞线程
t3.join()
自定义线程即重写线程
自定义线程与重写进程类似,也是通过创建新的线程类,然后使用新的线程类继承Thread的方法实现,再重写run方法即可
代码示例
# encoding: utf-8
from threading import Thread, current_thread, Lock
class MyThread(Thread):
def __init__(self, name):
Thread.__init__(self)
self.name = name
def run(self):
for i in range(5):
print("正在进行自定义线程中的第{}次任务".format(i), os.getpid(), os.getppid())
time.sleep(0.5)
if __name__ == '__main__':
t5 = MyThread(name="自定义线程") # 创建自定义线程对象并指定线程名
t5.start() # 启动自定义线程对象
t5.join()
print("t5线程名::",t5.name) # 查看当前线程名
输出结果
正在进行自定义线程中的第0次任务 70502 390
正在进行自定义线程中的第1次任务 70502 390
正在进行自定义线程中的第2次任务 70502 390
正在进行自定义线程中的第3次任务 70502 390
正在进行自定义线程中的第4次任务 70502 390
t5线程名:: 自定义线程
通过多线程实现卖票代码示例(代码中)
# encoding: utf-8
from threading import Thread, current_thread, Lock
ticket = 10
def sale_ticket():
global ticket
while True:
if ticket > 0:
print("{}正在出售第{}张票".format(current_thread().name, ticket))
ticket -= 1
time.sleep(0.5)
else:
print("{}提示:票卖完了!!".format(current_thread().name))
break
if __name__ == '__main__':
t6 = Thread(target=sale_ticket, name="一号窗口") # 创建线程对象,并指定线程名
t7 = Thread(target=sale_ticket, name="二号窗口")
t8 = Thread(target=sale_ticket, name="三号窗口")
t9 = Thread(target=sale_ticket, name="四号窗口")
t10 = Thread(target=sale_ticket, name="五号窗口")
t6.start() # 启动线程
t7.start()
t8.start()
t9.start()
t10.start()
输出结果
一号窗口正在出售第10张票
二号窗口正在出售第9张票
三号窗口正在出售第8张票
四号窗口正在出售第7张票
五号窗口正在出售第6张票
二号窗口正在出售第5张票
四号窗口正在出售第4张票 # 在线程执行过程中可能会出现类似问题
一号窗口正在出售第4张票
三号窗口正在出售第2张票
五号窗口正在出售第1张票
二号窗口提示:票卖完了!!
四号窗口提示:票卖完了!!
一号窗口提示:票卖完了!!
三号窗口提示:票卖完了!!
五号窗口提示:票卖完了!!
可以从输出结果中看出,代码在执行时会出现重复卖的票与漏卖的,这是因为线程在执行时使用的是一个全局变量,就会出现不同线程在同一时间处理同一个任务。解决这一办法就是为线程加上一个GIL锁,下篇笔记记述线程锁的使用