在现代计算机应用和编程中,充分利用多核处理能力是提高计算性能和效率的重要手段之一。而编程中最常见的并行编程方式之一就是多线程编程,它能够在一个单独的程序中同时执行多个任务,从而提高整个应用程序的执行效率。Python作为一款主流编程语言,其也提供了多线程编程的相关支持。本文将基于这一主题,针对Python多线程编程技术的相关内容进行详细阐述。
一、Python多线程怎么写
Python多线程编程即在一个程序中创建多个执行线程,其中主线程继续运行,而子线程则通过调用一定的函数并完成相应的任务。Python标准库中提供了Thread类,是一个默认的线程类,可以通过多个实例来创建相应的线程;常用的还有Thread类的派生类——即Thread子类,这个类可以通过重写Thread类的run方法来完成相应的处理。下面是一个简单的Python多线程编程示例,通过继承Thread类、重写run方法,并绑定相应的参数,完成对不同函数调用的多线程执行:
import threading class MyThread(threading.Thread): def __init__(self, func, args): super(MyThread, self).__init__() self.func = func self.args = args def run(self): self.result = self.func(*self.args) def get_result(self): try: return self.result except Exception: return None def add(x, y): return x+y def subtract(x, y): return x-y def multiply(x, y): return x*y def divide(x, y): return x/y if __name__=="__main__": threads = [] lists = [(1, 2), (5, 4), (2, 5), (2, 2)] for item in lists: t1 = MyThread(add, item) t2 = MyThread(subtract, item) t3 = MyThread(multiply, item) t4 = MyThread(divide, item) threads.append(t1) threads.append(t2) threads.append(t3) threads.append(t4) for t in threads: t.start() for t in threads: t.join() print(t.get_result())
在该示例中,我们继承了Python标准库中的Thread类,并通过构造函数和run方法来完成线程的对应功能。通过控制线程的调度,可以实现多个线程的并行执行,从而提高整个程序的性能。
二、Python多线程调用同一个函数
在Python多线程编程中,有时我们需要对同一个函数进行并行调用,从而加快相应的计算速度。Python提供了针对同一个函数并行调用的方法,其中最常见的是使用ThreadPoolExecutor类,它通过异步、可调用和饱和策略等特点实现了多线程执行。下面是针对Python多线程调用同一个函数的一个简单示例:
from concurrent.futures import ThreadPoolExecutor def my_func(x, y): return x+y if __name__=="__main__": with ThreadPoolExecutor(max_workers=2) as executor: future1 = executor.submit(my_func, 1, 2) future2 = executor.submit(my_func, 3, 4) print(future1.result()) print(future2.result())
在该示例中,我们定义了一个名为my_func的函数,并指定了相应的参数;并且利用Python的ThreadPoolExecutor类对该函数进行了异步并行调用,最终得到相应的结果。
三、Python多线程并行
在Python多线程编程中,最大的好处之一就是能够并行处理,即进行多个任务的同时处理。并行能够提高程序的执行效率,缩短程序的运行时间。下面是Python多线程并行的一个简单示例:
import time import threading def func(): print('Begin Func') time.sleep(5) print('End Func') def main(): threads = [] for i in range(5): t = threading.Thread(target=func) threads.append(t) t.start() for t in threads: t.join() if __name__ == '__main__': main()
在该示例中,我们通过Python多线程并行方式实现了对func()函数的多次调用。通过控制不同线程的调度来实现并行处理,从而提高整个程序的效率。
四、Python多线程多进程
Python多线程和多进程的区别在于前者主要是在同一个进程内执行,而后者则是不同的进程之间执行。根据任务的不同,我们可以选择多进程或者多线程。下面是Python多线程和多进程之间的简单对比:
1、Python多进程编程适用于计算密集型任务,即需要大量CPU计算的任务,因为在多进程编程中,Python将会为主进程和子进程分配不同的CPU时间和资源,从而加快相应任务的执行。
2、Python多线程编程适用于I/O密集型任务,即需要读取或者写入数据的任务。因为I/O密集型任务主要是在等待外部处理,Python多线程编程可以通过进一步并行处理来提高相应任务的效率。
因此,在Python编程中,我们需要根据不同的任务需求来选择多进程或者多线程编程方式。
五、Python多线程停止控制
在Python多线程编程中,我们需要能够对不同的线程进行停止控制,从而控制整个程序的运行。Python提供了多种停止线程的方式,具体如下:
1、使用自定义标志或者异常:在多线程编程中,我们可以使用自定义标志或者异常来停止特定的线程。这个方法比较简单,但是需要线程在特定的时间挂起,从而完成停止。
2、使用Thread.alive()函数:在Python多线程编程中,我们也可以利用Thread.alive()函数判断线程是否处于活动状态,进而完成线程的停止控制。
3、使用Event对象:Python提供了Event对象,通过wait和set函数可以实现线程的条件同步,进而实现线程的停止控制。
六、Python多线程下载
在Python多线程编程中,我们经常需要对不同的资源进行下载。Python提供了相应的并行加下载的方式来加快下载的效率,具体如下:
1、使用urlib库实现并行下载:urllib是Python的标准库之一,可以通过其urlretrieve函数来下载文件。并行下载可以通过Python多线程编程实现。下面是一个示例:
import urllib.request import time import threading import os,sys def file_get(url): try: filename = os.path.basename(url) data = urllib.request.urlopen(url,timeout=5) f = open('E:\\DownloadFiles\\'+filename,'wb') f.write(data.read()) f.close() except Exception as e: print(e) class MyThread(threading.Thread): def __init__(self, func, args, name=''): threading.Thread.__init__(self) self.name = name self.func = func self.args = args def getResult(self): return self.res def run(self): self.res = self.func(*self.args) if __name__=='__main__': urls = ["http://www.jyw.cn/2021/njffmm_0409/31.jpg", "http://pic.pimg.tw/asia-english/1363724244-916205393.jpg", "http://pic.pimg.tw/asia-english/1363724244-916205393.jpg"] for url in urls: t = MyThread(file_get,(url,)) t.start()
2、使用ThreadPoolExecutor类实现多线程下载:下面是相对应的示例:
import concurrent.futures import urllib.request img_urls = [ 'http://blog.hexu.pro/images/avatar-default.png', # ... ] def download_img(img_url): img_filename = img_url.split('/')[-1] + ".jpg" urllib.request.urlretrieve(img_url, img_filename) return f'({img_song}: {img_filename})' with concurrent.futures.ThreadPoolExecutor() as executor: results = executor.map(download_img, img_urls) for result in results: print(result)
七、Python多线程运行原理
Python多线程运行原理与其他编程语言中多线程运行原理类似,都是采用多进程编程方式,即在一个主进程下开辟多个子线程并行执行不同的任务,进而提高程序的执行效率。与其他语言不同的是,Python中存在GIL全局解释器锁的问题,即同一时刻同一进程中只会有一个线程处于运行状态,其他线程处于挂起状态,无法继续执行。为了解决这个问题,Python引入了多进程编程方式,即在不同进程之间进行并行计算。
八、Python多线程实例
下面是一个针对Python多线程编程实例的示例——简单的针对正方形和圆形的区域计算程序。具体代码如下:
from threading import Thread, Lock import time mutex = Lock() class SquareArea: def __init__(self): self.total = 0 def add_square_area(self, start, end): mutex.acquire() for i in range(start, end): self.total += i * i mutex.release() class CircleArea: def __init__(self): self.total = 0 def add_circle_area(self, start, end): mutex.acquire() for i in range(start, end): self.total += i * i * 3.14 mutex.release() if __name__ == '__main__': square_area = SquareArea() circle_area = CircleArea() t1 = Thread(target=square_area.add_square_area, args=(0, 1000000)) t2 = Thread(target=circle_area.add_circle_area, args=(0, 1000000)) t1.start() t2.start() t1.join() t2.join() print(square_area.total) print(circle_area.total)
在该示例中,我们定义了一个计算正方形面积和圆形面积的多线程程序,采用互斥锁的方式来实现线程的同步控制,从而避免了多线程编程的常见问题,同时可以达到较好的程序效率和性能。
九、Python多线程和多进程的区别
Python多线程和多进程区别在于,前者主要是在同一个进程内执行多个线程,而后者则是在不同的进程之间执行。具体而言,Python多线程和多进程的区别有以下几个方面:
1、Python多线程的好处主要体现在能够提高I/O操作等任务完成的效率,而多进程的优势则在于其能够充分发挥计算机CPU的效率,从而加快算法的执行。
2、Python多线程的缺点主要在于存在GIL全局解释器锁的问题,这个问题会导致多线程无法充分发挥多核CPU的效率,从而降低程序的性能,而多进程则不存在这个问题。