进程 与 线程

  • 进程就是操作系统中执行的一个程序
  • 一个进程,可以有多个线程

进程与线程

Python既支持多进程又支持多线程,因此使用Python实现并发编程主要有3种方式:

  • 多进程
  • 多线程
  • 多进程+多线程

操作系统可以同时执行多个任务,每一个任务就是一个进程。进程可以同时执行多个任务,每一个任务就是一个线程。

单进程

任务依次进行

from random import randint
from time import time, sleep


def download_task(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()
    download_task('东哥的Python私房菜.pdf')
    download_task('大英博物馆-世界简史.pdf')
    end = time()
    print('总共耗费了%.2f秒.' % (end - start))


if __name__ == '__main__':
    main()

多进程

需要使用 multiprocessing 模块的 Process

from multiprocessing import Process
from os import getpid
from random import randint
from time import time, sleep


def download_task(filename):
    print('启动下载进程,进程号[%d].' % getpid())
    print('开始下载%s...' % filename)
    time_to_download = randint(5, 10)
    sleep(time_to_download)
    print('%s下载完成! 耗费了%d秒' % (filename, time_to_download))


def main():
    start = time()
    p1 = Process(target=download_task, args=('东哥的Python私房菜.pdf', ))
    p1.start()
    p2 = Process(target=download_task, args=('大英博物馆-世界简史.pdf', ))
    p2.start()
    p1.join()
    p2.join()
    end = time()
    print('总共耗费了%.2f秒.' % (end - start))


if __name__ == '__main__':
    main()

通过 Process 类创建了进程对象,通过 target 参数我们传入一个函数来表示进程启动后要执行的代码,后面的 args 是一个元组,它代表了传递给函数的参数。Process 对象的 start 方法用来启动进程,而 join 方法表示等待进程执行结束。

运行上面的代码可以明显发现两个下载任务同时启动了,而且程序的执行时间将大大缩短。

多线程

需要使用 threading 模块的 Thread

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=('东哥的Python私房菜.pdf',))
    t1.start()
    t2 = Thread(target=download, args=('大英博物馆-世界简史.pdf',))
    t2.start()
    t1.join()
    t2.join()
    end = time()
    print('总共耗费了%.3f秒' % (end - start))


if __name__ == '__main__':
    main()

使用继承的方式,实现多线程

from random import randint
from threading import Thread
from time import time, sleep


class DownloadTask(Thread):
    def __init__(self, filename):
        super().__init__()
        self._filename = filename

    def run(self):
        print('开始下载%s...' % self._filename)
        time_to_download = randint(5, 10)
        sleep(time_to_download)
        print('%s下载完成! 耗费了%d秒' % (self._filename, time_to_download))


def main():
    start = time()
    t1 = DownloadTask('东哥的Python私房菜.pdf')
    t1.start()
    t2 = DownloadTask('大英博物馆-世界简史.pdf')
    t2.start()
    t1.join()
    t2.join()
    end = time()
    print('总共耗费了%.2f秒.' % (end - start))


if __name__ == '__main__':
    main()