Python研究学习--12--多线程编程(上)

版权声明:本文为博主原创文章,转载本站文章请注明作者和出处,请勿用于任何商业用途。 https://blog.csdn.net/wutianxu123/article/details/82528467

12.1 理论基础

单线程:独立的任务挨个运行
多线程:独立的任务同时运行。底层是将一个大任务分多线程,线程流水线式运行

举例:假定有两个循环函数。一个需10秒运行结束,另一个需12秒运行结束
单线程:挨个运行,共需22秒运行结束
多线程:同时运行,共需12秒运行结束(以时间长的子线程运行时间为准)
不使用锁:主线程自定义等待时间(足够所有子线程运行结束),等待时间结束后主线程继续运行
—–注意!如果不自定义等待时间,则可能主线程运行结束了子线程还没运行完
使用锁:主线程不用自定义时间,子线程运行结束后释放锁,主线程立即继续运行
不使用守护线程:主线程若退出,则子线程无论是否运行结束都会强制退出
使用守护线程:主线程若退出,受守护的子线程不会退出,不受守护的子线程强制退出

使用模块及语法:

import thread                 #不推荐使用,适合高级底层专家使用
import threading              #更高级、更全面。推荐使用
import Queue                  #可以创建队列数据结构,使其在多线程之间共享

threading模块中的对象(类):

方法 解释
Thread 表示一个执行线程的对象
Lock 锁原语对象
RLock 可重入锁对象,使单一线程可以(再次)获得已持有的锁(递归锁)
Condition 条件变量对象,使得一个线程等待另一个线程满足特定的“条件”
Event 条件变量的通用版本,任意数量的线程等待某个事件的发生,在该事件发生后所有线程将被激活
Semaphore 为线程间共享的有限资源提供了一个“计数器”,如果没有可用资源时会被阻塞
BoundedSemaphore 与Semaphore相似,不过它不允许超过初始值
Timer 与Thread相似,不过它要在运行前等待一段时间

threading模块中thread类的对象和方法:

Thread对象数据属性

方法 解释
name 线程名
ident 线程的标识符
daemon 布尔标志,表示这个线程是否是守护线程

Thread对象方法

方法 解释
init() 实例化一个线程对象。注意是单下划线
start() 开始执行该线程
run() 定义线程功能的方法(通常在子类中被应用开发者重写)
join(timeout=None) 直至启动的线程终止之前一直挂起;除非赋予等待值,否则会一直阻塞

threading模块中的其它函数:

方法 解释
enumerate() 返回当前活动的Thread对象列表
settrace(func) 为所有线程设置一个trace函数
setprofile(func) 为所有线程设置一个profile函数
stack_size(size=0) 返回新创建线程的栈大小;或为后续创建的线程设定栈的大小为size

Queue模块的常用属性:
Queue模块的类

方法 解释
Queue(最大值) 创建一个先入先出队列。如果给定最大值,则在队列没有空间时阻塞;否则为无限队列
LifoQueue(最大值) 创建一个后入先出队列。如果给定最大值,则在队列没有空间时阻塞;否则为无限队列
PriorityQueue(最大值) 创建一个优先级队列。如果给定最大值,则在队列没有空间时阻塞,否则为无限队列

Queue异常

方法 解释
Empty 当对空队列调用get*()方法时抛出异常
Full 当对已满的队列调用put*()方法时抛出异常

Queue对象方法

方法 解释
qsize() 返回队列大小(该值为近似值)
empty() 如果队列为空,则返回 True;否则,返回 False
full() 如果队列已满,则返回 True;否则,返回 False
put(item,block,timeout) 将item 放入队列。若block为 True且timeout为None,则在有可用空间之前阻塞;如果timeou为正值,则最多阻塞 timeout秒;如果block为False,则抛出Empty异常
put_nowait(item) 和 put(item,False)相同
get(block,timeout) 从队列中取得元素。如果给定了block,则一直阻塞到有可用的元素为止
get_nowait() 和 get(False)相同
task_done() 用于表示队列中的某个元素已执行完成,该方法会被下面的join()使用
join() 在队列中所有元素执行完毕并调用上面的task_done()信号之前,保持阻塞

多线程编程相关模块:

方法 解释
thread 基本的、低级别的线程模块
threading 高级别的线程和同步对象
multiprocessing 使用“threading”接口派生/使用子进程
subprocess 完全跳过线程,使用进程来执行
Queue 供多线程使用的同步先入先出队列
mutex 互斥对象
SocketServer 创建/管理线程控制的TCP/UDP服务器

串讲—Python程序的执行顺序:
以最外面的代码由上至下执行,函数/类代码没有顺序,只有在调用他们的时候执行。

12.2 使用Threading模块创建线程

代码实例:

# -*- coding: UTF-8 -*-

import threading                                #导入模块
from time import sleep,ctime

loops=(12,8)                                    #变量赋值。分别是12秒和8秒

class mythread(threading.Thread):               #定义类。继承父类
    def __init__(self,func,args,name=''):       #定义类内的初始函数(__init__函数),用于接收传参
        threading.Thread.__init__(self)         #父类(Thread)中的初始函数的声明
        self.name=name                          #将函数参数转换为类内全局变量
        self.func=func     
        self.args=args

    def run(self):                              #定义表示线程活动的函数
        self.func(*self.args)                   #全局声明

def loop(nloop,nsec):                           #定义函数。有两个变量(括号里致使变量名而已)
    print u"\n循环%s,开始时间为:%s" % (nloop,ctime())
    sleep(nsec)
    print u"循环",nloop,u"完成时间:",ctime()

def main():                                     #定义主函数
    print u"开始:",ctime()                      #开始时间。即时取时
    threads=[]                                  #定义了一个空列表。列表名为threads
    nloops=range(len(loops))                    #len(loops)=2,range(len(loops))=[0,1]。即两个列表值

    for i in nloops:                            #第一个循环
        t = mythread(loop,(i,loops[i]),loop.__name__)        #定义实参了
        threads.append(t)                       #整个类加进来了
    for i in nloops:                            #第二个循环
        threads[i].start()                      #启动线程活动
    for m in nloops:                            #第三个循环
        threads[m].join()                       #等待线程终止
    print u"都已完成:",ctime()

if __name__=="__main__":                        #独立运行脚本的惯用方法,判断函数是否为主程序
    main()

代码实例:

# -*- coding: UTF-8 -*-

import threading
import time

exitFlag = 0

class myThread (threading.Thread):                 #继承父类threading.Thread
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):                                 #把要执行的代码写到run函数里面线程在创建后会直接运行run函数 
        print u"开始" + self.name
        print_time(self.name, self.counter,5)      #调用函数。同时对函数传入实参
        print u"退出" + self.name

def print_time(threadName, delay, counter):        #定义函数。有三个形参(括号里只是变量名而已),接收实参传入
    while counter:
        if exitFlag:                               #if语句,和代码头处的想对应
            threading.Thread.exit()                #退出
        time.sleep(delay)
        print "%s: %s" % (threadName, time.ctime(time.time()))
        counter -= 1                               #counter=counter-1

thread1 = myThread(1, "xiancheng-1", 1)            #创建新线程。类的实例化,传递三个参数给类,类接收
thread2 = myThread(2, "xiancheng-2", 2)

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

print u"退出主线程"

猜你喜欢

转载自blog.csdn.net/wutianxu123/article/details/82528467
今日推荐