Python常用模块之threading和Thread模块及线程通信

  

Python常用模块之threading和Thread模块及线程通信

简介

Python中可以使用Thread模块和threading模块来创建线程。其中Thread模块是低级模块,用于低级别的线程控制,而threading模块是高级模块,对Thread模块进行了封装,使得线程更加方便使用。本文将对这两个模块进行详细讲解,并讨论线程之间是如何进行通信的。

基本使用方法

使用Thread模块创建线程

使用Thread模块创建线程,需要完成以下步骤:

  1. 导入Thread模块
  2. 定义一个函数,作为线程要执行的任务
  3. 创建Thread对象,将定义的函数作为参数传递给它
  4. 调用Thread对象的start方法,启动线程

下面是一个示例代码:

import thread
import time

# 线程函数
def my_thread(name, delay):
    count = 0
    while count < 5:
        time.sleep(delay)
        count += 1
        print(name, "执行了", count, "次")

# 创建两个线程,并启动它们
try:
    thread.start_new_thread(my_thread, ("线程1", 1))
    thread.start_new_thread(my_thread, ("线程2", 2))
except:
    print("线程创建失败")

while True:
    pass # 无限循环,保持主线程不关闭

以上代码创建了两个线程,并启动它们。这两个线程会分别每秒钟和每两秒钟执行一次,分别输出"线程1"和"线程2"。

使用threading模块创建线程

使用threading模块创建线程,需要完成以下步骤:

  1. 导入threading模块
  2. 定义一个类,继承自threading.Thread,重写run方法作为线程要执行的任务
  3. 创建线程对象,将自定义的线程类实例作为参数传递给它
  4. 调用线程对象的start方法,启动线程

下面是一个使用threading模块创建线程的示例代码:

import threading
import time

# 线程类
class MyThread(threading.Thread):
    def __init__(self, name, delay):
        super().__init__()
        self.name = name
        self.delay = delay

    def run(self):
        count = 0
        while count < 5:
            time.sleep(self.delay)
            count += 1
            print(self.name, "执行了", count, "次")

# 创建两个线程,并启动它们
try:
    t1 = MyThread("线程1", 1)
    t2 = MyThread("线程2", 2)
    t1.start()
    t2.start()
except:
    print("线程创建失败")

while True:
    pass # 无限循环,保持主线程不关闭

这个代码与使用Thread模块创建线程的代码是等效的。

线程通信

Python中的线程之间可以使用多种方式进行通信,常见的方式包括:

  1. 使用共享变量
  2. 使用队列
  3. 使用事件

使用共享变量

共享变量是多个线程可以访问并修改的变量。对于共享变量,需要使用线程锁来保证数据的正确性。

下面是一个使用共享变量进行线程通信的示例代码:

import threading
import time

# 共享变量
g_num = 0
g_num_lock = threading.Lock()

# 线程类
class MyThread(threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        global g_num
        while True:
            g_num_lock.acquire() # 获得线程锁
            if g_num >= 10:
                g_num_lock.release() # 如果已经大于等于10,就释放线程锁
                break
            g_num += 1
            print(self.name, "把 g_num 变成了", g_num)
            g_num_lock.release() # 释放线程锁

# 创建两个线程,并启动它们
try:
    t1 = MyThread("线程1")
    t2 = MyThread("线程2")
    t1.start()
    t2.start()
except:
    print("线程创建失败")

while True:
    if g_num >= 10:
        break
    time.sleep(1)

print("所有线程执行结束")

以上代码使用了一个共享变量g_num,两个线程不断对它进行加1操作,并输出结果。如果g_num已经大于等于10,则线程执行结束。

使用队列

队列是一个线程安全的数据结构,可以用来在线程之间传递数据。队列提供了put和get方法,分别用于将数据加入队列和从队列中取出数据。当队列为空或已满时,put和get方法会阻塞。

下面是一个使用队列进行线程通信的示例代码:

import threading
import time
from queue import Queue

# 队列
q = Queue()

# 线程类
class ProducerThread(threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        while True:
            if q.qsize() < 10:
                q.put(1)
                print(self.name, "向队列中加入了一个数据,当前队列大小为", q.qsize())
                time.sleep(1)
            else:
                print("队列已满,等待1秒")
                time.sleep(1)

class ConsumerThread(threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        while True:
            if q.qsize() > 0:
                q.get()
                print(self.name, "从队列中取出了一个数据,当前队列大小为", q.qsize())
                time.sleep(1)
            else:
                print("队列已空,等待1秒")
                time.sleep(1)

# 创建两个线程,并启动它们
try:
    t1 = ProducerThread("生产者线程")
    t2 = ConsumerThread("消费者线程")
    t1.start()
    t2.start()
except:
    print("线程创建失败")

while True:
    pass # 无限循环,保持主线程不关闭

以上代码包含了一个生产者线程和一个消费者线程,生产者线程将数据加入队列,消费者线程从队列中取出数据。当队列已满或已空时,线程会等待1秒再进行操作。

使用事件

事件是一种线程同步机制,用于在线程之间传递信号。事件有set和clear方法,分别用于设置和清除事件标志,wait方法用于阻塞线程,直到事件标志被设置。

下面是一个使用事件进行线程通信的示例代码:

import threading
import time

# 事件
e = threading.Event()

# 线程类
class WaitThread(threading.Thread):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print(self.name, "等待事件触发")
        e.wait() # 等待事件
        print(self.name, "收到了事件")

# 创建线程并启动它
try:
    t = WaitThread("等待线程")
    t.start()
except:
    print("线程创建失败")

time.sleep(2) # 等待2秒

# 触发事件
e.set()
print("事件被触发")

while True:
    pass # 无限循环,保持主线程不关闭

以上代码包含了一个等待线程和一个触发事件的主线程。等待线程调用wait方法等待事件触发,而主线程使用set方法触发事件,并输出相关信息。

相关文章