Python 多线程

本文介绍了Python的多线程使用,包括thread和Threading模块的线程创建,探讨了线程同步问题,强调了join方法在多线程同步中的作用,并提到了Lock和Rlock对象用于线程安全的数据操作。同时,还提及了优先级队列Queue的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python中的多线程与Java,C++中的思想是比较接近的,作用也一样:

  • 使用线程可以把占据长时间的程序中的任务放到后台去处理。
  • 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
  • 程序的运行速度可能加快
  • 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。

Python通过两个标准库thread和threading提供对线程的支持。

使用thread模块创建线程

函数式:调用thread模块中的start_new_thread()函数来产生新线程。语法如下:

thread.start_new_thread ( function, args[, kwargs] )
  • function - 线程函数。
  • args - 传递给线程函数的参数,他必须是个tuple类型。
  • kwargs - 可选参数。
#-*-coding: utf-8 -*-
import thread
import time
#定义线程函数
def print_time(threadName,delay):
    count = 0
    while count<5:
        time.sleep(delay)
        count += 1
        print "%s: %s" % (threadName,time.ctime(time.time()))
#创建两个线程
def test():
    thread.start_new_thread(print_time, ("Thread-1", 1,))
    thread.start_new_thread(print_time, ("Thread-2", 2,))
if __name__=="__main__":
    test()
    """
    防止Unhandled exception in thread started by Error in sys.excepthook问题。
    启动线程之后,须确保主线程等待所有子线程返回结果后再退出,如果主线程比子线程早结束,无论其子线程是否是后台线程,都将会中断,抛出这个异常 。
    """
    time.sleep(30)

使用Threading模块创建线程

使用Threading模块创建线程,直接从threading.Thread继承,然后重写init方法和run方法:

#-*- coding:utf-8 -*-
import random

import threading
import time
"""
注意文件名不要与python保留字一样,会出现AttributeError:'module' object has no attribute 'Thread'
threading模块中包含方法和Thread类:
"""
#使用Threading模块创建线程,直接从threading.Thread继承,然后重写__init__方法和run方法
exitFlag = 0
class myThread(threading.Thread):
    def __init__(self,threadID,threadName,delay):
        #调用父类的构造方法
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.threadName = threadName
        self.delay = delay
    def run(self):
        print "Starting" + self.threadName
        print_time(self.threadName,self.delay,5)
        print "Exiting" + self.threadName
def print_time(threadName,delay,counter):
    while counter:
        if exitFlag:
            threading.Thread.exit()
        time.sleep(delay)
        print "%s: %s" % (threadName,time.ctime(time.time()))
        counter -= 1
#创建线程
thread1 = myThread(1,"Thread-1",1)
thread2 = myThread(2,"Thread-2",2)
#开启线程
thread1.start()
thread2.start()

print "Exiting Main Thread"

线程的同步问题

多线程同步知识点:
一:
当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,
主线程会创建多个子线程,在python中,默认情况下(其实就是setDaemon(False)),
主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束。
二:
当我们使用setDaemon(True)方法(默认为False),设置子线程为守护线程时,主线程一旦执行结束,则全部线程
全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止,例如:

    for t in thread_list:
        t.setDaemon(True)
        t.start()

三:
此时join的作用就凸显出来了,join所完成的工作就是线程同步,即主线程任务结束之后,
进入阻塞状态,一直等待其他的子线程执行结束之后,主线程在终止。

使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。如下:

#-*- coding: utf-8 -*-
import threading
import time

class myThread(threading.Thread):
    def __init__(self,threadID,threadName,delay):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.threadName = threadName
        self.delay = delay
    def run(self):
        print "Starting" + self.threadName
        #获得锁,成功获得锁后返回True
        #可选的timeout不填时将一直阻塞
        #否则超时后将返回False
        threadLock.acquire()
        print_time(self.threadName,self.delay,3)
        #释放锁
        threadLock.release()

def print_time(threadName,delay,counter):
    while counter:
        time.sleep(delay)
        print "%s: %s" % (threadName, time.ctime(time.time()))
        counter -= 1


threadLock = threading.Lock()
threads = []
start_time = time.time()
print('Main Thread', threading.current_thread().name)
#创建线程
thread1 = myThread(1,"Thread-1",1)
thread2 = myThread(2,"Thread-2",2)

#开启新线程
thread1.start()
thread2.start()

#添加线程到线程列表
threads.append(thread1)
threads.append(thread2)

#等待所有线程完成
"""
join关键点:
1.我们的计时是对主线程计时,主线程结束,计时随之结束,打印出主线程的用时。
2.主线程的任务完成之后,主线程随之结束,子线程继续执行自己的任务,直到全部的子线程的任务全部结束,程序结束。
"""
for t in threads:
    t.join()
#可以看到,主线程一直等待全部的子线程结束之后,主线程自身才结束,程序退出。
print "Exiting Main Thread"
print('Main Thread Over' , threading.current_thread().name)
print('the all time', time.time()-start_time)

优先级队列Queue

#-*- coding:utf-8 -*-
import Queue
import threading
import time

exitFlag = 0
class myThread(threading.Thread):
    def __init__(self,ThreadID,name,q):
        threading.Thread.__init__(self)
        self.ThreadID = ThreadID
        self.name = name
        self.q = q
    def run(self):
        print "Starting: " + self.name
        process_data(self.name,self.q)
        print "Exiting: " + self.name
#取出队列中的元素
def process_data(threadName,q):
    while not exitFlag:
        queueLock.acquire()
        if workQueue.empty():
            queueLock.release()
        else:
            data = workQueue.get()
            queueLock.release()
            print "%s processing %s" % (threadName,data)
        time.sleep(1)


threadList = ["Thread-1","Thread-2","Thread-3"]
nameList = ["One","Two","Three","Four","Five"]
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
threads = []
threadID = 1
#创建线程
for tName in threadList:
    thread =  myThread(threadID,tName,workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1
#填充队列
queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()
#等待清空队列
while not workQueue.empty():
    pass
#通知线程退出
exitFlag = 1
#等待所有线程退出
for t in threads:
    t.join()
print "Exiting Main Thread"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值