您的位置:

Python多线程编程实战:利用Thread实现并发任务处理

Python的多线程编程在实际应用中扮演着很重要的角色,能够大大提升程序的性能,缩短运行时间,改善用户体验。在Python中,我们可以使用Thread类来实现多线程编程,它提供了简单易用的接口,让我们很容易地利用多线程实现并发任务处理。在这篇文章中,我们将从以下几个方面详细介绍如何利用Thread实现多线程编程。

一、Thread类简介

Thread类是Python中多线程编程的核心类,使用它我们可以很容易地创建和管理多个线程。在Python中,每个线程都是一个Thread类的实例,每个线程都有一个唯一的标识符,我们可以通过该标识符来区分不同的线程。Thread类提供了以下几个常用方法:

Thread(target=None, args=(), kwargs={})
start()
run()
join([timeout])

①Thread()方法:创建一个新线程,可设置线程的目标函数、位置参数和关键字参数。

②start()方法:启动线程,使其处于就绪状态。

③run()方法:定义线程的功能,通过覆盖该方法来编写线程的功能代码。

④join()方法:等待线程终止。

二、多线程编程实战

1、利用Thread实现多线程编程

下面是一个简单的例子,利用Thread类实现并发任务处理。

import threading
import time
 
def job():
    for i in range(5):
        print "Thread:", threading.current_thread().name, " Processing:", i
        time.sleep(1)

if __name__ == '__main__':
    threads = []
    for i in range(3):
        t = threading.Thread(target=job)
        t.start()
        threads.append(t)
    for t in threads:
        t.join()
    print "All threads done!"

执行结果如下所示:

Thread: Thread-1  Processing: 0
Thread: Thread-2  Processing: 0
Thread: Thread-3  Processing: 0
Thread: Thread-1  Processing: 1
Thread: Thread-2  Processing: 1
Thread: Thread-3  Processing: 1
Thread: Thread-1  Processing: 2
Thread: Thread-2  Processing: 2
Thread: Thread-3  Processing: 2
Thread: Thread-1  Processing: 3
Thread: Thread-2  Processing: 3
Thread: Thread-3  Processing: 3
Thread: Thread-1  Processing: 4
Thread: Thread-2  Processing: 4
Thread: Thread-3  Processing: 4
All threads done!

上述代码中,首先定义一个job函数,它用于模拟一个需要执行的任务,在任务中我们使用了time.sleep()模拟任务的执行时间。然后创建一个含有3个线程的线程池,并且将job函数作为线程的目标函数,并启动线程。最后,使用join()方法等待所有线程执行完毕。

2、利用Thread实现线程池

在实际开发中,我们可能需要创建大量的线程来处理任务,但是线程的创建和销毁代价很高,为了减少这种开销,我们可以使用线程池来管理线程。下面是一个基于Thread类实现的简单线程池示例。

import threading
import time

class ThreadPool(object):
    def __init__(self, max_threads):
        self.max_threads = max_threads
        self._threads = []
        self._lock = threading.Lock()

    def apply_async(self, func, *args, **kwargs):
        self._lock.acquire()
        try:
            if len(self._threads) >= self.max_threads:
                raise Exception("Max threads exceeded")
            t = threading.Thread(target=func, args=args, kwargs=kwargs)
            t.start()
            self._threads.append(t)
        finally:
            self._lock.release()

    def join(self):
        for t in self._threads:
            t.join()

def job(i):
    print "Thread:", threading.current_thread().name, " Processing:", i
    time.sleep(1)

if __name__ == '__main__':
    pool = ThreadPool(3)
    for i in range(9):
        pool.apply_async(job, i)
    pool.join()
    print "All threads done!"

执行结果如下所示:

Thread: Thread-1  Processing: 0
Thread: Thread-2  Processing: 1
Thread: Thread-3  Processing: 2
Thread: Thread-4  Processing: 3
Thread: Thread-5  Processing: 4
Thread: Thread-6  Processing: 5
Thread: Thread-7  Processing: 6
Thread: Thread-8  Processing: 7
Thread: Thread-9  Processing: 8
All threads done!

上述代码中,我们首先创建了一个ThreadPool类,它包含了最大线程数、线程列表和锁等属性。然后定义了apply_async()和join()两个方法,apply_async()函数用于向线程池中加入新的线程,并启动线程执行指定的任务;join()函数通过join()方法等待所有线程执行完毕。最后,我们使用ThreadPool类创建了一个含有3个线程的线程池,并向线程池中加入了9个任务,最后使用join()方法等待所有任务都完成。

三、多线程编程实战技巧

1、避免共享资源冲突

在多线程编程中,经常会涉及到共享资源的访问,例如多个线程需要同时访问同一个列表,这时就需要注意避免资源冲突问题。

import threading

class Counter(object):
    def __init__(self):
        self.num = 0
        self.lock = threading.Lock()

    def add(self, n):
        self.lock.acquire()
        try:
            self.num += n
        finally:
            self.lock.release()

if __name__ == '__main__':
    c = Counter()
    t1 = threading.Thread(target=c.add, args=(1,))
    t2 = threading.Thread(target=c.add, args=(2,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print "counter:", c.num

执行结果如下所示:

counter: 3

上述代码中,我们定义了一个Counter类,它含有一个num属性和一个锁。在add函数中,我们使用了锁来确保对共享资源的访问不会引起冲突。在程序运行时,我们创建了两个线程分别执行add函数,最后使用join()方法等待所有线程执行完毕,并输出结果。

2、线程间通信

在多线程编程中,线程间通信是非常常见的需求,例如生产者和消费者问题、信号量等。Python提供了一些用于线程间通信的模块,例如Queue、Condition、Event等。下面是一个简单的利用Queue实现线程间通信的示例。

import threading
import time
import Queue

class Consumer(threading.Thread):
    def __init__(self, name, queue):
        threading.Thread.__init__(self)
        self.name = name
        self.queue = queue

    def run(self):
        while True:
            if self.queue.qsize() > 0:
                item = self.queue.get()
                print "Consumer %s get item %s" % (self.name, item)
            
class Producer(threading.Thread):
    def __init__(self, name, queue):
        threading.Thread.__init__(self)
        self.name = name
        self.queue = queue

    def run(self):
        for i in range(5):
            item = "item" + str(i)
            self.queue.put(item)
            print "Producer %s put item %s" % (self.name, item)
            time.sleep(1)

if __name__ == '__main__':
    queue = Queue.Queue(10)
    p1 = Producer("P1", queue)
    p2 = Producer("P2", queue)
    c1 = Consumer("C1", queue)
    c2 = Consumer("C2", queue)
    p1.start()
    p2.start()
    c1.start()
    c2.start()
    p1.join()
    p2.join()
    c1.join()
    c2.join()
    print "All threads done!"

执行结果如下所示:

Producer P1 put item item0
Consumer C1 get item item0
Producer P2 put item item1
Consumer C2 get item item1
Producer P1 put item item2
Consumer C2 get item item2
Producer P2 put item item3
Consumer C1 get item item3
Producer P1 put item item4
Consumer C2 get item item4
All threads done!

上述代码中,我们创建了一个含有10个位置的队列,并定义了Producer和Consumer两个类分别用于生产者和消费者的线程执行。在Producer的run()方法中,我们向队列中放入5个item;在Consumer的run()方法中,我们使用了queue.qsize()方法判断队列是否为空,如果不为空,则获取队列中的item并输出;最后使用join()方法等待所有线程执行完毕,并输出结果。

总结

本文介绍了Python多线程编程的一些知识和实践技巧,重点讲解了Thread类的使用、线程池的实现、共享资源冲突的避免、线程间通信等方面的内容。希望本文能够对大家在实际开发中的多线程编程有所帮助。