• python多线程之threading


    一。创建线程的方法

    1.用 thread.Thread 直接在线程中运行函数

    import threading  
      
    def threadfun(x,y):         #线程任务函数 threadfun()  
        for i in range(x,y):  
            print(i)  
      
    ta = threading.Thread(target=threadfun,args=(1,6))      #创建一个线程ta,执行 threadfun()  
    tb = threading.Thread(target=threadfun,args=(10,15))    #创建一个线程tb,执行threadfun()  
    ta.start()          #调用start(),运行线程  
    tb.start()          #调用start(),运行线程  
    '''''打印:1 2 3 4 5 10 11 12 13 14'''  

    2.通过继承 thread.Thread 类 来创建线程 

    这种方法只需要重载 threading.Thread 类的 run 方法,然后调用 start()开启线程就可以了

    import threading  
      
    class mythread(threading.Thread):  
        def run(self):  
            for i in range(1,5):  
                print(i)  
      
    ma = mythread();  
    mb = mythread();  
    ma.start()  
    mb.start()  

    3.创建Thread实例,传给它一个可调用的类的实例

    import threading
    from time import sleep,ctime
    
    loops=[4,2]
    
    class ThreadFunc(object):
        def __init__(self,func,args,name=''):
            self.name=name
            self.func=func
            self.args=args
    
        def __call__(self):
            self.func(*self.args)
    
    def loop(nloop,nsec):
        print 'start loop',nloop,'at:',ctime()
        sleep(nsec)
        print 'loop',nloop,'done at:',ctime()
    def main():
        print 'starting at:',ctime()
        threads=[]
        nloops=range(len(loops))
        nloop=range(len(loops))
    
        for i in nloops:
            t=threading.Thread(target=ThreadFunc(loop,(i,loops[i]),loop.__name__))
            threads.append(t)
    
        for i in nloops:
            threads[i].start()
    
        for i in nloops:
            threads[i].join()
    
        print 'alll DONE at:',ctime()
    
    
    if __name__=='__main__':
        main()

    3.join方法

    join()作用是 调用 join() 的线程 阻塞直到 某一线程结束才继续执行

    import threading  
    import time  
    class mythread(threading.Thread):  
        def run(self):  
            self.i = 1  
            print('%d'%(self.i))  
            self.i = self.i+1  
            time.sleep(1)           #睡眠一秒  
            print('%d'%(self.i))  
            time.sleep(1)  
      
    if __name__ == '__main__':  
        ta = mythread()     #实例化线程  
        ta.start()          #开启ta线程  
        ta.join()           #主线程等待 ta线程结束才继续执行  
        print('main thread over')   

    4.isAlive()方法

    这个方法用于判断线程是否存在

    1.当线程未调用 start()来开启时,isAlive()会返回False

    2.但线程已经执行后并结束时,isAlive()也会返回False

    import threading  
    import time  
    class mythread(threading.Thread):  
        def run(self):  
           time.sleep(2)  
      
    if __name__ == '__main__':  
        ta = mythread()     #实例化线程  
        print(ta.isAlive())   #打印False,因为未执行 start()来使ta线程运行  
        ta.start()  
        print(ta.isAlive())   #打印Ture,因为ta线程运行了  
        time.sleep(3)  
        print(ta.isAlive())   #打印False,因为ta线程已经结束了 

    5.Thread对象数据属性,name(线程名),ident(线程的标识符),daemon(布尔标识,表示这个线程是否是守护线程)

    5.1设置为守护线程的方法:在启动线程之前执行:thread.daemon=True.查询是否为守护线程,isDaemon(),设置线程的守护标志为布尔值,setDaemon(daemonic)在start()之前调用

    5.2name属性表示线程的线程名 默认是 Thread-x  x是序号,由1开始,第一个创建的线程名字就是 Thread-1

    import threading  
    import time  
    class mythread(threading.Thread):  
        def run(self):  
            pass  
      
    if __name__ == '__main__':  
        ta = mythread()     #实例化线程  
        ta.name = 'thread-ta'  
        tb = mythread()  
        tb.start()  
        ta.start()  
      
        print(ta.name)  #打印 thread-ta  
        print(tb.name)  #打印 Thread-2  

    5.3    daemon属性用来设置线程是否随主线程退出而退出

    当 daemon = False 时,线程不会随主线程退出而退出(默认时,就是 daemon = False)

    当 daemon = True 时,当主线程结束,其他子线程就会被强制结束

    import threading  
    import time  
    class mythread(threading.Thread):  
        def run(self):  
            time.sleep(2)  
            print('my thread over')  
      
    def main():  
        ta = mythread()  
        ta.daemon = True  
        ta.start()  
        print('main thread over')  
      
    if __name__ == '__main__':  
        main()  
    #打印结果 :main thread over   然后马上结束程序  

    6.线程同步———锁

    当一个进程拥有多个线程之后,如果他们各做各的任务互没有关系还行,但既然属于同一个进程,他们之间总是具有一定关系的。比如多个线程都要对某个数据进行修改,则可能会出现不可预料的结果。为保证操作正确,就需要引入锁来进行线程间的同步。

    python3 中的 threading 模块提供了 RLock锁(可重入锁)。对于某一时间只能让一个线程操作的语句放到 RLock的acquire 方法 和 release方法之间。即 acquire()方法相当于给RLock 锁  上锁,而 release() 相当于解锁。

    import threading  
    import time  
      
    class mythread(threading.Thread):  
        def run(self):  
            global x            #声明一个全局变量  
            lock.acquire()      #上锁,acquire()和release()之间的语句一次只能有一个线程进入,其余线程在acquire()处等待  
            x += 10  
            print('%s:%d'%(self.name,x))  
            lock.release()      #解锁  
      
    x = 0  
    lock = threading.RLock()    #创建 可重入锁  
    def main():  
        l = []  
        for i in range(5):  
            l.append(mythread())    #创建 5 个线程,并把他们放到一个列表中  
        for i in l:  
            i.start()               #开启列表中的所有线程  
      
    if __name__ =='__main__':  
        main()  

    打印结果:

    Thread-1:10
    Thread-2:20
    Thread-3:30
    Thread-4:40
    Thread-5:50

    7.线程的同步——Event对象

    Event对象存在于 threading 模块中。Event 实例管理着 一个内部标志,通过 set() 方法来将该标志设置成 True,使用 clear() 方法将该标志重置成 False

    wait() 方法会使当前线程阻塞直到标志被设置成 True,wait()可以选择给他一个参数,代表时间,代表阻塞多长时间,若不设置就是阻塞直到标志被设置为True

    isSet()方法  :能判断标志位是否被设置为True

    import threading  
    import time  
      
    class Mon(threading.Thread):  
        def run(self):  
            Dinner.clear()  
            print('Cooking dinner')  
            time.sleep(3)  
            Dinner.set()    #标志设置为True  
            print(self.name,':dinner is OK!')  
      
    class Son(threading.Thread):  
        def run(self):  
            while True:  
                if Dinner.isSet():  #判断标志位是否被设置为True  
                    break  
                else:  
                    print('dinner isnot ready!')  
                    Dinner.wait(1)  
      
            print(self.name,':Eating Dinner')  
      
    def main():  
        mon = Mon()  
        son = Son()  
        mon.name = 'Mon'  
        son.name = 'Son'  
        mon.start()  
        son.start()  
      
    if __name__ == '__main__':  
        Dinner = threading.Event()  
        main()  
      
    ''''' 
    Cooking dinner 
    dinner isnot ready! 
    dinner isnot ready! 
    dinner isnot ready! 
    Mon :dinner is OK! 
    Son :Eating Dinner 
    '''  

    8.线程的同步----Condition条件变量

    条件变量表示当线程满足某一个 条件才被唤醒,否则一直阻塞

    对比 只用锁不用条件变量 的好处就是:只用锁的话,如果一个线程在上锁后,解锁前,因为某一条件一直阻塞着,那么锁就一直解不开,那么其他线程也就因为一直获取不了锁而跟着阻塞着,这样效率就不好,浪费了很多时间。对于这种情况,锁+条件变量可以让该线程先 解锁,然后阻塞着,等待条件满足了,再重新唤醒并获取锁(上锁)。这样就不会因为一个线程阻塞着而影响其他线程也跟着阻塞了。

    Condition 提供的方法:

    acquire() 和 release() 表示上锁和解锁,和 单纯的锁机制一样。

    wait()  解开锁,阻塞,直到其他线程调用了notify()或者notifyAll才被唤醒,注意,这里的wait()跟上面Event提到的wait()不是同一样东西

    notify() 发出资源可用的信号,唤醒任意一条因 wait()阻塞的进程

    notifyAll() 发出资源可用信号,唤醒所有因wait()阻塞的进程

    下面给出一个例子,一家蛋糕店:只会做一个蛋糕,卖出后才会再做一个。绝对不会做积累到2个蛋糕。

    import threading  
    import time  
      
    class Server(threading.Thread):  
        def run(self):  
            global x  
            while True:  
                con.acquire()  
                while x>0:  
                    con.wait()  
                x += 1  
                time.sleep(1)  
                print(self.name,':I make %d cake!'%(x))  
                con.notifyAll()  
                con.release()  
      
    class Client(threading.Thread):  
        def run(self):  
            global x  
            con.acquire()  
            while x == 0:  
                con.wait()  
            x-=1  
            print(self.name,'I bought a cake! the rest is %d cake'%(x))  
            con.notifyAll()  
            con.release()  
      
    def main():  
        ser = Server()  
        ser.name = 'Cake Server'  
        client = []  
        for i in range(3):  
            client.append(Client())  
        ser.start()  
        for c in client:  
            c.start()  
      
    if __name__ =='__main__':  
        x = 0  
        con = threading.Condition()  
        main()  
    ''''' 
    打印结果: 
    Cake Server :I make 1 cake! 
    Thread-3 I bought a cake! the rest is 0 cake 
    Cake Server :I make 1 cake! 
    Thread-4 I bought a cake! the rest is 0 cake 
    Cake Server :I make 1 cake! 
    Thread-2 I bought a cake! the rest is 0 cake 
    Cake Server :I make 1 cake! 
    '''  
  • 相关阅读:
    POJ1741
    聪聪可可
    [USACO07NOV]Cow Relays
    Android 程序的反破解技术
    在Android上实现SSL握手(客户端需要密钥和证书),实现服务器和客户端之间Socket交互
    vmware中的bridge、nat、host-only的区别
    史上最易懂的Android jni开发资料--NDK环境搭建
    使用javah生成.h文件, 出现无法访问android.app,Activity的错误的解决
    Android apk反编译基础(apktoos)图文教程
    Smali文件语法解析
  • 原文地址:https://www.cnblogs.com/qingsheng/p/8870371.html
Copyright © 2020-2023  润新知