• Python 多线程


    其实自我感觉Python的多线程很类似于Java的多线程机制,但是比JAVA的多线程更灵活。在早期的Python多线程实现中,采用了thread模块。例如:   

       

    Python代码
    from time import ctime,sleep
    from thread import start_new_thread
    def loop1():
        print "enter loop1:",ctime();
        sleep(3);
        print "leave loop1:",ctime();
    
    def loop2():
        print "enter loop2:",ctime();
        sleep(5);
        print "leave loop2:",ctime();
    
    def main():
        print "main begin:",ctime();
        start_new_thread(loop1, ());
        start_new_thread(loop2,());
        sleep(8);
        print "main end:",ctime();
    
    if __name__=="__main__":
        main();

        简单介绍下这个代码块中的函数功能,sleep是线程睡眠时间,几乎等价于JAVA中的Thread.sleep(millionseconds)

        start_new_thread是实例化一个线程并运行的方法,方法的第一个参数接受一个线程运行时所执行的函数对象,第二个参数是方法执行时所需要的参数,以一个元组的形式传入。   

        这大概是最早期的Python多线程实现了,注意代码中的main线程里的sleep(8)。这里的睡眠时间只能比3+5大,而不能小。如果小于这个时 间,那么main主线程会提前退出,导致无论其子线程是否是后台线程,都将会中断,从而抛出线程中断异常,类似于Java的 ThreadInterruptException。这个致命的影响几乎就是这个模块后期被抛弃的罪魁祸首。

        当然在早期的Python多线程中,你可以利用加锁的机制来避免出现这个情况。稍微改动下以上代码:

        

    Python代码
    import thread;
    from time import sleep,ctime;
    from random import choice
    #The first param means the thread number
    #The second param means how long it sleep
    #The third param means the Lock
    def loop(nloop,sec,lock):
        print "Thread ",nloop," start and will sleep ",sec;
        sleep(sec);
        print "Thread ",nloop," end  ",sec;
        lock.release();
    
    def main():
        seconds=[4,2];
        locks=[];
        for i in range(len(seconds)) :
            lock=thread.allocate_lock();
            lock.acquire();
            locks.append(lock);
            
        print "main Thread begins:",ctime();
        for i,lock in enumerate(locks):
            thread.start_new_thread(loop,(i,choice(seconds),lock));
        for lock in locks :
            while lock.locked() : 
                pass;
        print "main Thread ends:",ctime();
    
    if __name__=="__main__" :
        main();

        这里对Python线程运行时加入了锁监控机制,介绍下红色字体标志的几个方法(其实红色字体中的lock实质是thread.lockType实例。 ):

        从以上介绍可以看出这个Lock类非常类似于JDK5.0中的java.util.concurrent.locks.Lock。不知道Doug Lea有没有参与这个模块的开发,哈哈~~(纯属YY),只是比JAVA中的LOCK类多了一个方法locked,用于检测Lock对象是否还处于加锁的状态。

        所以上一个例子的工作原理就是在启动线程的时候,给每个线程都加了一把锁,直到线程运行介绍,再释放这个锁。同时在Python的main线程中用一个 while循环来不停的判断每个线程锁已释放。这个方法虽然避免了最开始的例子中人为的时间控制,但是还不方便,高效。

        所以在较新的Python版本中,都推荐使用threading模块。

        看下threading模块的API,有过JAVA开发经验的会发现它和java.lang.Thread类非常接近。这里需要说的一点就是threading的run方法可以返回函数值,这点在用于跟踪和判断线程运行正常与否非常有作用。

       threading模块支持三种方法来创建线程。而前两种方式都与其Thread类有关。看下它的简要说明:

        

    class Thread(_Verbose) :
         __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None)

       这里只是将target指向从一个函数对象变成了一个可调用的类实例。

        重点推荐下第三种方式,用继承threading.Thread的方式来实现线程,有过Java多线程应用的朋友一定会对下面的例子非常熟悉。

       

    Python代码  

     

    from time import ctime,sleep
    import threading;
    from random import choice
    
    def loop(number,sec):
        print "Thread ",number," begins and will sleep ",sec," at ",ctime();
        sleep(sec);
        print "Thread ",number,"ends at ",ctime();
        
    def main():
        seconds=[2,4];
        threads=[];
        array=range(len(seconds));
        for i in array :
            t=threading.Thread(target=loop,args=(i,choice(seconds)));
            threads.append(t);
        print "main Thread begins at ",ctime();
        for t in threads :
            t.start();
        for t in threads :
            t.join();        
        print "main Thread ends at ",ctime();
    
    if __name__=="__main__" :
        main();


     

        从上面可以看出MyThread继承了threading.Thread类,并在初始化方法中执行了必要的参数赋值。值得注意的是在Java类的继承中, 如果不显示的指定调用父类的构造方法,那么默认将调用父类的无参构造方法。而在Python中,就不会主动去调用。所以这里需要显示的调用父类的初始化方 法

  • 相关阅读:
    首评 | 阿里云顺利完成国内首个云原生安全成熟度评估
    基于任务调度的企业级分布式批处理方案
    阿里云发布性能测试 PTS 2.0:低成本、高效率、多场景压测,业务稳定性保障利器
    OpenKruise v1.2:新增 PersistentPodState 实现有状态 Pod 拓扑固定与 IP 复用
    ZooKeeper 在阿里巴巴的服务形态演进
    阿里云微服务引擎 MSE 5 月产品动态
    应用实时监控服务ARMS 5 月功能快报&优惠汇总
    618 大促来袭,浅谈如何做好大促备战
    「技术人生」第8篇:如何画业务大图
    Serverless Job——传统任务新变革
  • 原文地址:https://www.cnblogs.com/demonspider/p/3250848.html
Copyright © 2020-2023  润新知