Python单线程与多线程

最近一直在学习爬虫的相关知识,目前学习到了单线程、多线程这一块,把自己的学习经历分享出来顺便也做个笔记。

多线程与多进程

首先我们要明白,单线程、多线程、多进程、多机器
简单来说如下图所示

在写程序时经常要合理选择多线程与多进程,这两者各有优势,并不存在谁好谁坏,根据需求来进行选择,
一般多线程适合I/O密集型,多进程适合CPU密集型


一.单线程操作

单线程操作就是我们日常写代码时的操作,为了比较出和多线程的区别,以下为其对比。

#使用单线程串行方式执行
import time
def get_page(str):
    print('正在下载:',str)
    time.sleep(2)
    print('下载成功:',str)

name_list = ['xiaozi','aa','bb','cc']
start_time = time.time()
for i in range(len(name_list)):
    get_page(name_list[i])
end_time  = time.time()
print('%d second' % (end_time-start_time))
正在下载: xiaozi
下载成功: xiaozi
正在下载: aa
下载成功: aa
正在下载: bb
下载成功: bb
正在下载: cc
下载成功: cc
8 second

二.多线程操作

循环

首先引入多线程模块

import time
import threading
def get_page(str):
    print('正在下载:',str,'\n')
    time.sleep(2)
    print('下载成功:',str,'\n')

name_list = ['xiaozi','aa','bb','cc']
start_time = time.time()
for name in name_list:
    t = threading.Thread(target=get_page,args=(name,))
    t.start()

运行之后可以发现

正在下载: xiaozi
正在下载: aa
正在下载: bb
正在下载: cc
下载成功: xiaozi
下载成功: aa
下载成功: cc
下载成功: bb
2 second

池化

import time
from concurrent.futures import ThreadPoolExecutor,as_completed
def get_page(str):
    print('正在下载:',str,'\n')
    time.sleep(2)
    print('下载成功:',str,'\n')

name_list = ['xiaozi','aa','bb','cc']
start_time = time.time()
with ThreadPoolExecutor() as pool:
    # 方法一
    results = pool.map(get_page,name_list)
    for result in results:
        print(result)
  
  
    #方法二
    futures = [pool.submit(get_page,name) for name in name_list]
    # 方法二的第一种输出方法,按照顺序,会堵塞
    for future in futures:
        print(future.result())
    # 方法二的第二种输出方法,不按照顺序,不会堵塞
    for future in as_completed(futures):
        print(future.result())

二.多进程操作

循环

import time
from multiprocessing import Process
def get_page(str):
    print('正在下载:',str,'\n')
    time.sleep(2)
    print('下载成功:',str,'\n')

name_list = ['xiaozi','aa','bb','cc']
start_time = time.time()
for name in name_list:
    t = Process(target=get_page,args=(name,))
    t.start()

池化

import time
from concurrent.futures import ProcessPoolExecutor,as_completed
def get_page(str):
    print('正在下载:',str,'\n')
    time.sleep(2)
    print('下载成功:',str,'\n')

name_list = ['xiaozi','aa','bb','cc']
start_time = time.time()
with ProcessPoolExecutor() as pool:
    # 方法一
    results = pool.map(get_page,name_list)
    for result in results:
        print(result)
  
  
    #方法二
    futures = [pool.submit(get_page,name) for name in name_list]
    # 方法二的第一种输出方法,按照顺序,会堵塞
    for future in futures:
        print(future.result())
    # 方法二的第二种输出方法,不按照顺序,不会堵塞
    for future in as_completed(futures):
        print(future.result())

目前我个人来说使用的方式一般是单线程+异步协程。
我将在下一篇文章中进行相关的记录,说明。
希望大家给点个赞,如有错误,望指出。

最后修改:2023 年 11 月 24 日
如果觉得我的文章对你有用,请随意赞赏