1. 线程介绍
1.1 什么是线程
线程(Thread)也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。
1.2 为什么要使用多线程
线程在程序中是独立的、并发的执行流。与分隔的进程相比,进程中线程之间的隔离程度要小,它们共享内存、文件句柄和其他进程应有的状态。
因为线程的划分尺度小于进程,使得多线程程序的并发性高。进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
线程比进程具有更高的性能,这是由于同一个进程中的线程都有共性多个线程共享同一个进程的虚拟空间。线程共享的环境包括进程代码段、进程的公有数据等,利用这些共享的数据,线程之间很容易实现通信。
操作系统在创建进程时,必须为该进程分配独立的内存空间,并分配大量的相关资源,但创建线程则简单得多。因此,使用多线程来实现并发比使用多进程的性能要高得多。
总结起来,使用多线程编程具有如下几个优点:
- 进程之间不能共享内存,但线程之间共享内存非常容易。
- 操作系统在创建进程时,需要为该进程重新分配系统资源,但创建线程的代价则小得多。因此,使用多线程来实现多任务并发执行比使用多进程的效率高。
- Python 语言内置了多线程功能支持,而不是单纯地作为底层操作系统的调度方式,从而简化了 Python 的多线程编程。
2. 线程实现
这里我们使用threading模块
2.1 普通创建方式
import threading
import time
def run(n):
print ('task',n)
time.sleep(1)
print ('2s')
time.sleep(1)
print ('1s')
time.sleep(1)
print ('0s')
time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=run,args=('t1',))
t2 = threading.Thread(target=run,args=('t2',))
t1.start()
t2.start()
task t1
task t2
2s
2s
1s
1s
0s
0s
下面我们来看一下多线程是否会提高代码运行速度
- 普通方式
import cv2
import numpy as np
import time
def test(img):
#平均滤波器
blur1 = cv2.blur(img,(5,5))
#中值滤波器
blur2 = cv2.medianBlur(img,5)
#高斯滤波器
blur3 = cv2.GaussianBlur(img,(5,5,),0)
#双边滤波器,同时考虑像素的空间位置和邻域的像素灰度相似性,在滤波的同时较好的保留图片的边缘
blur4 = cv2.bilateralFilter(img,9,75,75)
start = time.time()
img = cv2.imread('digits.png')
test(img)
end = time.time()
print ('runtime:',(end-start)*100)
runtime: 11.170053482055664
- 使用多线程
import threading
def blur(img):
blur1 = cv2.blur(img,(5,5))
def medianBlur(img):
blur2 = cv2.medianBlur(img,5)
def gaussianBlur(img):
blur3 = cv2.GaussianBlur(img,(5,5,),0)
def bilateralFilter(img):
blur4 = cv2.bilateralFilter(img,9,75,75)
start = time.time()
img = cv2.imread('digits.png')
t1 = threading.Thread(target=blur,args=(img,))
t2 = threading.Thread(target=medianBlur,args=(img,))
t3 = threading.Thread(target=gaussianBlur,args=(img,))
t4 = threading.Thread(target=bilateralFilter,args=(img,))
t1.start()
t2.start()
t3.start()
t4.start()
end = time.time()
runtime = end-start
print ('runtime:',runtime*100)
runtime: 2.69315242767334
对比可以知道,多线程使得程序快了很多
2.2 自定义线程
继承threading.Thread来自定义线程类,其本质是重构Thread类中的run方法
import threading
import time
class MyThread(threading.Thread):
def __init__(self,n):
super(MyThread,self).__init__()#重构run函数
self.n = n
def run(self):
print ('task ',self.n)
time.sleep(1)
print ('2s')
time.sleep(1)
print ('1s')
time.sleep(1)
print ('0s')
if __name__ == '__main__':
t1 = MyThread('t1')
t2 = MyThread('t2')
t1.start()
t2.start()
task t1
task t2
2s
2s
1s
1s
0s
0s