并发编程(Concurrent or Parallel Programming)

本章将介绍第7️⃣种编程范式--- 并发编程的优缺点,案例分析和代码,以及一个小项目,来体会一下并发编程在实际项目中的作用。

优点

并发编程的优点:

  1. 提高性能:允许多个任务同时执行,可以更充分地利用计算资源,提高程序的性能。
  2. 改善响应性:在某些情况下,通过并发处理可以改善系统对外部事件的响应,使系统更加灵活和交互性更强。
  3. 资源共享:允许多个任务共享系统资源,如内存、文件等,提高资源的利用效率。
  4. 模块化设计:可以更容易地设计模块化和可重用的代码,将程序划分为独立的任务,使得程序结构更清晰。
  5. 提高系统可靠性:并发编程可以提高系统的可靠性和健壮性,因为即使某个任务失败,其他任务仍然可以继续执行。

缺点

并发编程的缺点:

  1. 复杂性增加:并发编程引入了线程和线程之间的同步和通信问题,增加了程序的复杂性和难度。
  2. 调试困难:由于并发引入了并发性错误,例如竞态条件和死锁,调试和排查问题可能更加困难。
  3. 性能开销:并发程序可能引入一些性能开销,例如线程切换、同步操作等,有时可能导致性能下降。
  4. 非确定性:并发程序的执行是非确定性的,不同的执行顺序可能导致不同的结果,这增加了程序的理解和测试的难度。
  5. 死锁和饥饿:并发程序容易出现死锁(多个任务相互等待对方释放资源)和饥饿(某一任务一直无法获得资源)等问题。

并发编程的案例分析

一个常见的并发编程案例是Web服务器。多个客户端可能同时请求服务器上的资源,服务器需要同时处理多个连接,这就需要并发编程来实现多线程或多进程处理这些请求,以提高服务器的吞吐量和响应速度。

并发编程的代码示例

以下是一个简单的Python多线程示例,演示了如何使用"threading"模块创建两个线程并发执行任务:

import threading
import time

def task(name):
    for i in range(5):
        print(f"Thread {name}: Task {i}")
        time.sleep(1)

# 创建两个线程
thread1 = threading.Thread(target=task, args=("A",))
thread2 = threading.Thread(target=task, args=("B",))

# 启动线程
thread1.start()
thread2.start()

# 等待两个线程执行完毕
thread1.join()
thread2.join()

print("Main Thread: All tasks completed.")

在这个例子中,两个线程“thread1”和“thread2”同时执行“task”函数,模拟了并发执行的情况。

小项目--多线程并发下载图片

下面是一个简单的并发编程小项目示例,该项目使用Python的“concurrent.futures”模块中的"ThreadPoolExecutor"实现多线程并发下载图片的任务。该项目通过并行下载图片,提高了下载效率。

import concurrent.futures
import requests
import os

def download_image(url, save_path):
    response = requests.get(url)
    with open(save_path, "wb") as file:
        file.write(response.content)
    print(f"Downloaded {url} to {save_path}")

def main():
    # 图片链接列表
    image_urls = [
        'https://example.com/image1.jpg',
        'https://example.com/image2.jpg',
        'https://example.com/image3.jpg',
        # ...可以添加更多图片链接
    ]
    
    # 创建保存图片的目录
    save_directory = "downloaded_images"
    os.makedirs(save_directory, exist_ok=True)
    
    # 使用ThreadPoolExecutor创建线程池
    with concurrent.futures.ThreadPoolExecutor() as executor:
        # 提交下载任务
        future_to_url = {executor.submit(download_image, url, f"            
           {save_directory}/image{i}.jpg"):url for i, url in enumerate(image_urls)}
        
        # 等待所有任务完成
        for future in concurrent.futures.as_completed(future_to_url):
            url = future_to_url[future]
            try:
                future.result()
            except Exception as e:
                print(f"Error downloading {url}: {e}")

if __name__ == "__main__":
    main()
        
        
    

在这个小项目中,“download_image”函数用于下载单个图片,“main”函数负责调度并发下载任务。通过使用“ThreadPoolExecutor”,可以同时下载多张图片,提高了下载效率。

本章的项目和示例代码, 见GitHub

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值