多线程类似于同时执行多个不同程序,多线程运行有如下优点:
-1 使用线程可以把占据长时间的程序中的任务放到后台去处理。
-2 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度程序的运行速度可能加快
-3 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。
-4 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。
指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
线程可以被抢占(中断)。在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) -- 这就是线程的退让。
Python中使用线程有两种方式:函数或者用类来包装线程对象。
下面我以两个简单的示例来解释这两种方式:
模拟用多线程下载文件,用的是函数的方法:
from random import randint
from threading import Thread
from time import time, sleep
def download(filename):
print('开始下载%s...' % filename)
time_to_download = randint(5, 10)
sleep(time_to_download)
print('%s下载完成! 用时%d秒' % (filename, time_to_download))
def main():
start = time() # 开始的时间点
t1 = Thread(target=download, args=('A文件',)) # 注意字符串后面的逗号,表示传入的是元组
t1.start() # 启动下载A文件的线程
t2 = Thread(target=download, args=('B文件',))
t2.start()
t1.join() # 等待执行结束
t2.join() # 等待执行结束
end = time() # 结束的时间点
print('总共耗费了%.5f秒' % (end - start))
if __name__ == '__main__':
main()
用多线程写的赛车动画,五个线程控制五辆由色块表示的小车移动,这样小车可以同时移动,而不是一辆一辆依次移动
import pygame
from random import uniform, randint
from threading import Thread
class Car(object):
def __init__(self, x, y):
self._color = [randint(0, 255), randint(0, 255), randint(0, 255)]
self._x = x
self._y = y
@property
def x(self):
return self._x
def move(self):
self._x += uniform(0.5, 3)
def head(self):
return self._x + 20
def draw(self, screen):
pygame.draw.rect(screen, self._color, (self._x, self._y, 20, 20), 0)
def run(self, screen):
self.move()
self.draw(screen)
class Mythread(Thread):
def __init__(self, car, screen):
super().__init__()
self._car = car
self._screen = screen
def run(self):
Car.move(self._car)
Car.draw(self._car, self._screen)
def main():
pygame.init()
screen = pygame.display.set_mode([600, 500])
pygame.display.set_caption('赛车游戏')
screen.fill([255, 255, 255])
pygame.draw.line(screen, [0, 0, 0], (37, 0), (37, 500), 5)
pygame.draw.line(screen, [255, 0, 0], (580, 0), (580, 500), 5)
cars = []
for i in range(5):
car = Car(20, 50+100*i)
cars.append(car)
for car in cars:
car.draw(screen)
pygame.display.flip()
running = True
gameover = False
def game_over(c1):
nonlocal gameover
if c1.head() > 580:
gameover = True
def refresh():
screen.fill((255, 255, 255))
pygame.draw.line(screen, [0, 0, 0], (37, 0), (37, 500), 5)
pygame.draw.line(screen, [255, 0, 0], (580, 0), (580, 500), 5)
for _ in cars:
Mythread(_, screen).start()
pygame.display.flip()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
while not gameover:
for car in cars:
game_over(car)
refresh()
pygame.display.flip()
pygame.quit()
if __name__ == '__main__':
main()