Python 多线程

来源:互联网 发布:淘宝店铺标志图片大全 编辑:程序博客网 时间:2024/04/29 23:50

网上的一些关于python 多线程的好的总结,总结一下转了过来。


从Python2.4开始包含的较新的threading模块,为线程提供了更多强大、高级的支持。

threading模块包含了thread模块中所有的方法,并提供一些其余的方法:
 
  •  threading.activeCount():返回激活的线程对象的数目
  •  theading.currentThread():返回调用者的线程控制中线程对象的数目
  •  threading.enumerate(): 返回当前活动的线程对象列表
除了方法,threading模块有Thread类实现threading。Thread类提供的方法如下:

  •  run():线程的入口点
  •  start():调用run方法启动线程
  •  join(time):等待线程结束
  •  isAlive():检查一个线程是否仍旧在执行
  •  getName():返回线程的名字
  •  setName():设置一个线程的名字

使用Threading模块创建线程:

要使用threading模块实现一个新线程,你得先如下做:
  •   定义Thread类的一个子类。
  •  重写__init__(self,[,args])方法以增加额外的参数
  •  然后,重写run(self[,args])方法以实现线程启动后要做的事情
在你创建新的Thread子类以后,你可以创建它的一个实例,然后引用start()来开启一个新线程,它会依次调用call方法。


例子:
[python] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #!/usr/bin/python   
  2.   
  3. import threading  
  4. import time  
  5.   
  6. exitFlag = 0  
  7.   
  8. class myThread (threading.Thread):  
  9.     def __init__(self, threadID, name, counter):  
  10.         threading.Thread.__init__(self)  
  11.         self.threadID = threadID  
  12.         self.name = name  
  13.         self.counter = counter  
  14.     def run(self):  
  15.         print "Starting " + self.name  
  16.         print_time(self.name, self.counter, 5)  
  17.         print "Exiting " + self.name  
  18.   
  19. def print_time(threadName, delay, counter):  
  20.     while counter:  
  21.         if exitFlag:  
  22.             thread.exit()  
  23.         time.sleep(delay)  
  24.         print "%s: %s" % (threadName, time.ctime(time.time()))  
  25.         counter -= 1  
  26.   
  27. # Create new threads   
  28. thread1 = myThread(1"Thread-1"1)  
  29. thread2 = myThread(2"Thread-2"2)  
  30.   
  31. # Start new Threads   
  32. thread1.start()  
  33. thread2.start()  
  34.   
  35. print "Exiting Main Thread"  

上述代码执行后,它会产出如下结果:

Starting Thread-1
Starting Thread-2
Exiting Main Thread
Thread-1: Thu Mar 21 09:10:03 2013
Thread-1: Thu Mar 21 09:10:04 2013
Thread-2: Thu Mar 21 09:10:04 2013
Thread-1: Thu Mar 21 09:10:05 2013
Thread-1: Thu Mar 21 09:10:06 2013
Thread-2: Thu Mar 21 09:10:06 2013
Thread-1: Thu Mar 21 09:10:07 2013
Exiting Thread-1
Thread-2: Thu Mar 21 09:10:08 2013
Thread-2: Thu Mar 21 09:10:10 2013
Thread-2: Thu Mar 21 09:10:12 2013
Exiting Thread-2

互斥锁同步

上面的例子引出了多线程编程的最常见问题:数据共享。当多个线程都修改某一个共享数据的时候,需要进行同步控制。

线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

threading模块中定义了Lock类,可以方便的处理锁定:

#创建锁
mutex = threading.Lock()
#锁定
mutex.acquire([timeout])
#释放
mutex.release()

其中,锁定方法acquire可以有一个超时时间的可选参数timeout。如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁,从而可以进行一些其他的处理。

其实并不是给资源加锁, 而是用锁去锁定资源,你可以定义多个锁, 像下面的代码, 当你需要独占某一资源时,任何一个锁都可以锁这个资源

就好比你用不同的锁都可以把相同的一个门锁住是一个道理

 

[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #coding: utf-8  
  2. import  threading    
  3. import  time    
  4.      
  5. counter = 0  
  6. counter_lock = threading.Lock() #只是定义一个锁,并不是给资源加锁,你可以定义多个锁,像下两行代码,当你需要占用这个资源时,任何一个锁都可以锁这个资源  
  7. counter_lock2 = threading.Lock()   
  8. counter_lock3 = threading.Lock()  
  9.   
  10. #可以使用上边三个锁的任何一个来锁定资源  
  11.    
  12. class  MyThread(threading.Thread):#使用类定义thread,继承threading.Thread  
  13.      def  __init__(self,name):    
  14.         threading.Thread.__init__(self)    
  15.         self.name = "Thread-" + str(name)  
  16.      def run(self):   #run函数必须实现  
  17.          global counter,counter_lock #多线程是共享资源的,使用全局变量  
  18.          time.sleep(1);    
  19.          if counter_lock.acquire(): #当需要独占counter资源时,必须先锁定,这个锁可以是任意的一个锁,可以使用上边定义的3个锁中的任意一个  
  20.             counter += 1     
  21.             print "I am %s, set counter:%s"  % (self.name,counter)    
  22.             counter_lock.release() #使用完counter资源必须要将这个锁打开,让其他线程使用  
  23.               
  24. if  __name__ ==  "__main__":    
  25.     for i in xrange(1,101):    
  26.         my_thread = MyThread(i)  
  27.         my_thread.start()  

同步阻塞

当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“同步阻塞”(参见多线程的基本概念)。

直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。


3. 在threading.Thread中指定目标函数作为线程处理函数

Python代码  收藏代码
  1. # -*- coding: utf-8 -*-   
  2. from threading import Thread    
  3. def run_thread(n):    
  4.         for i in range(n):    
  5.             print i    
  6.     
  7. t1 = Thread(target=run_thread,args=(5,))#指定目标函数,传入参数,这里参数也是元组  
  8. t1.start()  #启动线程  

 

二. threading.Thread中常用函数说明

 

       函数名                                               功能run()如果采用方法2创建线程就需要重写该方法getName()获得线程的名称(方法2中有示例)setName()设置线程的名称start()启动线程join(timeout) 在join()位置等待另一线程结束后再继续运行join()后的操作,timeout是可选项,表示最大等待时间setDaemon(bool)True:当父线程结束时,子线程立即结束;False:父线程等待子线程结束后才结束。默认为FalseisDaemon()判断子线程是否和父线程一起结束,即setDaemon()设置的值isAlive() 判断线程是否在运行

 

以上方法中,我将对join()和setDaemon(bool)作着重介绍,示例如下:


(1)join方法:

Java代码  收藏代码
  1. # -*- coding: utf-8 -*-   
  2. import threading    
  3. import time     #导入time模块    
  4. class Mythread(threading.Thread):    
  5.     def __init__(self,threadname):    
  6.         threading.Thread.__init__(self,name = threadname)    
  7.     def run(self):    
  8.         time.sleep(2)   
  9.         for i in range(5):  
  10.             print '%s is running····'%self.getName()    
  11.      
  12. t2 = Mythread('B')    
  13. t2.start()  
  14. #t2.join()       
  15. for i in range(5):  
  16.     print 'the program is running···'  

 

这时的程序流程是:主线程先运行完,然后等待B线程运行,所以输出结果为:

 

Python代码  收藏代码
  1. the program is running···  
  2. the program is running···  
  3. the program is running···  
  4. is running····  
  5. is running····  
  6. is running····  
 

如果启用t2.join() ,这时程序的运行流程是:当主线程运行到 t2.join() 时,它将等待 t2 运行完,然后再继续运行t2.join() 后的操作,呵呵,你懂了吗,所以输出结果为:

 

Python代码  收藏代码
  1. is running····  
  2. is running····  
  3. is running····  
  4. the program is running···  
  5. the program is running···  
  6. the program is running···  

 

(2)setDaemon方法:

Python代码  收藏代码
  1. # -*- coding: utf-8 -*-   
  2. import threading  
  3. import time   
  4. class myThread(threading.Thread):  
  5.     def __init__(self, threadname):  
  6.         threading.Thread.__init__(self, name=threadname)  
  7.           
  8.     def run(self):  
  9.         time.sleep(5)  
  10.         print '%s is running·······done'%self.getName()  
  11.       
  12. t=myThread('son thread')  
  13. #t.setDaemon(True)  
  14. t.start()  
  15. if t.isDaemon():  
  16.     print "the father thread and the son thread are done"  
  17. else:  
  18.     print "the father thread is waiting the son thread····"  
 

这段代码的运行流程是:主线程打印完最后一句话后,等待son thread  运行完,然后程序才结束,所以输出结果为:

 

Python代码  收藏代码
  1. the father thread is waitting the son thread····  
  2. son thread is running·······done  

 

如果启用t.setDaemon(True) ,这段代码的运行流程是:当主线程打印完最后一句话后,不管 son thread 是否运行完,程序立即结束,所以输出结果为:

 

Python代码  收藏代码
  1. the father thread and the son thread are done  
 
0 0
原创粉丝点击