【从零学习python 】81.Python多线程通信与队列的应用

简介: 【从零学习python 】81.Python多线程通信与队列的应用

线程间通信

线程之间有时需要进行通信,而操作系统提供了多种机制来实现进程间的通信。其中,我们经常使用的一种方式是使用队列(Queue)。

Queue的原理

Queue是一个先进先出(First In First Out)的队列。主线程中创建一个Queue对象,并作为参数传递给子线程。通过put()方法将数据放入队列中,通过get()方法从队列中取出数据。在调用get()方法后,队列中的数据会被同时删除。我们可以使用multiprocessing模块中的Queue实现多线程之间的数据传递。

import threading
import time
from queue import Queue
# 生产者函数,用于将数据放入队列中
def producer(queue):
    for i in range(100):
        print('{}存入了{}'.format(threading.current_thread().name, i))
        queue.put(i)
        time.sleep(0.1)
# 消费者函数,用于从队列中取出数据
def consumer(queue):
    for x in range(100):
        value = queue.get()
        print('{}取到了{}'.format(threading.current_thread().name, value))
        time.sleep(0.1)
        if not value:
            return
if __name__ == '__main__':
    # 创建一个队列对象
    queue = Queue()
    # 创建多个线程,并将队列对象作为参数传递给线程函数
    t1 = threading.Thread(target=producer, args=(queue,))
    t2 = threading.Thread(target=consumer, args=(queue,))
    t3 = threading.Thread(target=consumer, args=(queue,))
    t4 = threading.Thread(target=consumer, args=(queue,))
    t6 = threading.Thread(target=consumer, args=(queue,))
    # 启动线程
    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t6.start()

在上述示例中,我们创建了一个Queue对象,并将其作为参数传递给多个线程。其中,producer函数用于将数据放入队列中,consumer函数用于从队列中取出数据。通过多个消费者线程的执行,可以实现多个线程之间对于共享队列的并发访问和通信。

具体代码解释如下:

  1. 导入所需的模块:threading用于创建和管理线程,time用于添加延迟效果,Queue用于创建队列对象。
  2. 定义生产者函数producer(queue),接收一个队列对象作为输入参数。该函数用于将数据放入队列中。
  3. 在生产者函数中使用一个循环,从0到99,将每个数字依次放入队列中。
  4. 使用threading.current_thread().name获取当前线程的名称,并打印存入的值。
  5. 使用queue.put(i)将数据放入队列中。
  6. 使用time.sleep(0.1)添加延迟效果。
  7. 定义消费者函数consumer(queue),同样接收一个队列对象作为输入参数。该函数用于从队列中取出数据。
  8. 在消费者函数中使用一个循环,从0到99,依次从队列中取出数据。
  9. 使用queue.get()获取队列中的数据,同时也会将该数据从队列中删除。
  10. 使用threading.current_thread().name获取当前线程的名称,并打印取出的值。
  11. 使用time.sleep(0.1)添加延迟效果。
  12. 如果取出的值为假值(即空),则返回函数,结束线程的执行。
  13. 在主程序中,创建一个队列对象queue
  14. 创建多个线程,并将队列对象作为参数传递给线程函数,分别创建了一个生产者线程和多个消费者线程。
  15. 启动线程,通过t.start()方法启动各个线程的执行。

通过以上代码,我们可以实现多个线程之间的通信,实现了生产者线程将数据放入队列中,多个消费者线程从队列中取出数据的过程。这样,我们就完成了线程间的通信。

相关文章
|
7天前
|
分布式计算 并行计算 安全
在Python Web开发中,Python的全局解释器锁(Global Interpreter Lock,简称GIL)是一个核心概念,它直接影响了Python程序在多线程环境下的执行效率和性能表现
【6月更文挑战第30天】Python的GIL是CPython中的全局锁,限制了多线程并行执行,尤其是在多核CPU上。GIL确保同一时间仅有一个线程执行Python字节码,导致CPU密集型任务时多线程无法充分利用多核,反而可能因上下文切换降低性能。然而,I/O密集型任务仍能受益于线程交替执行。为利用多核,开发者常选择多进程、异步IO或使用不受GIL限制的Python实现。在Web开发中,理解GIL对于优化并发性能至关重要。
25 0
|
1天前
|
安全 Java 调度
Python创建和结束线程
【7月更文挑战第1天】 - 启动线程:`thread.start()`,等待线程:`thread.join()`。 - 无法直接结束线程,通常通过设置标志位(如全局变量`is_running`)让线程自行退出。 - 使用`Event`对象(`stop_event.is_set()`)提供安全的线程结束方式。 - 异常处理:`try-except`捕获线程中异常,避免意外终止。
6 0
|
5天前
|
安全 Java 开发者
Python中的多线程高级使用方法
**Python多线程高级指南摘要** 本文探讨了Python中多线程的高级技术,尽管GIL限制了并行执行,但多线程仍适用于IO密集型任务和提升UI响应。内容包括: - 使用`threading`模块导入和创建线程,示例展示了如何启动多个线程执行函数。 - 高级用法涉及线程池,通过`ThreadPoolExecutor`管理线程,简化大量线程的创建和控制。 - 线程同步:介绍锁和条件变量的概念,以及如何使用它们确保数据一致性。 - 避免死锁的策略,如使用`try/finally`确保锁的正确释放 - 线程局部数据(Thread Local Data)允许每个线程拥有独立的数据副本,避免冲突
|
6天前
|
Java UED Python
Python多线程编程实战技巧与性能优化策略
Python多线程编程实战技巧与性能优化策略
|
10天前
|
存储 测试技术
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
15 0
【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试
|
11天前
|
数据采集 Java Unix
10-多线程、多进程和线程池编程(2)
10-多线程、多进程和线程池编程
|
11天前
|
安全 Java 调度
10-多线程、多进程和线程池编程(1)
10-多线程、多进程和线程池编程
|
15天前
|
存储 Linux C语言
c++进阶篇——初窥多线程(二) 基于C语言实现的多线程编写
本文介绍了C++中使用C语言的pthread库实现多线程编程。`pthread_create`用于创建新线程,`pthread_self`返回当前线程ID。示例展示了如何创建线程并打印线程ID,强调了线程同步的重要性,如使用`sleep`防止主线程提前结束导致子线程未执行完。`pthread_exit`用于线程退出,`pthread_join`用来等待并回收子线程,`pthread_detach`则分离线程。文中还提到了线程取消功能,通过`pthread_cancel`实现。这些基本操作是理解和使用C/C++多线程的关键。
|
18天前
|
安全 Java
【极客档案】Java 线程:解锁生命周期的秘密,成为多线程世界的主宰者!
【6月更文挑战第19天】Java多线程编程中,掌握线程生命周期是关键。创建线程可通过继承`Thread`或实现`Runnable`,调用`start()`使线程进入就绪状态。利用`synchronized`保证线程安全,处理阻塞状态,注意资源管理,如使用线程池优化。通过实践与总结,成为多线程编程的专家。
|
18天前
|
Java 开发者
告别单线程时代!Java 多线程入门:选继承 Thread 还是 Runnable?
【6月更文挑战第19天】在Java中,面对多任务需求时,开发者可以选择继承`Thread`或实现`Runnable`接口来创建线程。`Thread`继承直接但限制了单继承,而`Runnable`接口提供多实现的灵活性和资源共享。多线程能提升CPU利用率,适用于并发处理和提高响应速度,如在网络服务器中并发处理请求,增强程序性能。不论是选择哪种方式,都是迈向高效编程的重要一步。