python基础-线程创建方式

如何用python创建线程

python中提供了两种创建线程的方式

1.采用thread.start_new_thread(funciton,args..)

2.继承threading.Thread类

 

1.采用thread.start_new_thread(function,agrs..)方式

该方法的使用方式在官方手册中介绍的非常清楚

thread.start_new_thread(function, args[, kwargs])

Start a new thread and return its identifier. The thread executes the function function with the argument list args (which must be a tuple). The optional kwargs argument specifies a dictionary of keyword arguments. When the function returns, the thread silently exits. When the function terminates with an unhandled exception, a stack trace is printed and then the thread exits (but other threads continue to run).

来看一个例子

import thread as t
import time

#Define a function for the thread
def print_time(threadName,delay):
    count=0;
    while count<5:
        time.sleep(delay)
        count+=1
        print "%s(%s): %s " %(threadName,count,time.ctime(time.time()))

#Create two threads as follows
try:
    t.start_new_thread(print_time,("thread-1",2))
    t.start_new_thread(print_time,("thread-2",3))
except:
    print "Error:unable to start thread"

while 1:
    pass

2继承threading.Thread

thread是底层模板,threading模块对thread进行了封装。threading操作对线程操作进行了对象化,创建了Thread模块。

实现步骤如下

  1. 申明一个Thread类的子类
  2. 覆盖_init_(slef,agrs)方法来增加额外的参数
  3. 实现线程逻辑

 

import threading 
import time

exitFlag=0

class myThread(threading.Thread):
    #implement thead
    def __init__(self,threadID,name,delay):
        threading.Thread.__init__(self)
        self.threadID=threadID
        self.name=name
        self.delay=delay
       
    def run(self):
        print "Starting "+ self.name
        print_time(self.name,self.delay,5)
        print "Exiting "+ self.name

def print_time(threadName,delay,counter):
    while counter:
        if exitFlag:
            thread.exit() # 怎么引用当前的参数
        time.sleep(delay)
        print ("%s(%s): %s"%(threadName,counter,time.ctime(time.time())))
        counter -=1;

#Create new threads
thread1 = myThread(1,"Thread-1",1)
thread2 = myThread(2,"Thread-2",3)


#start
thread1.start()
thread2.start()#run和start不同,run直接调用了是

while thread2.isAlive():
    if not thread1.isAlive():
        exitFlag = 1
        print "thread1 is over"
    pass
print "Exiting Main Thread"

线程同步

如果涉及到多个线程对共享资源的访问时,就会出现线程不安全的情况,对于共享数据的抢占可能会导致结果不可预期的情况处理

import threading  
import time  
 
counter = 0  
 
class MyThread(threading.Thread):  
    def __init__(self):  
        threading.Thread.__init__(self)  
 
    def run(self):  
        global counter  
        time.sleep(1);  
        counter += 1  
        print "I am %s, set counter:%s" % (self.name, counter)  
 
if __name__ == "__main__":  
    for i in range(0, 200):  
        my_thread = MyThread()  
        my_thread.start()

运行结果部分如下,结果基本上没有什么规律

I am Thread-9,counter:==2==I am Thread-3,counter:==1==I am Thread-6,counter:==3==I am Thread-15,counter:==4==

 

 

threading.Lock

对于这种情况有一种方式就是采用互斥锁,设置一个全局互斥锁变量mutext = threading.Lock,在使用公共变量之前抢占互斥锁(mutex.acquire()),在使用完公共变量之后释放互斥锁定(mutex.release())

import threading  
import time  
 
counter = 0  
mutex = threading.Lock()  
 
class MyThread(threading.Thread):  
    def __init__(self):  
        threading.Thread.__init__(self)  
 
    def run(self):  
        global counter, mutex  
        time.sleep(1);  
        if mutex.acquire():  
            counter += 1  
            print "I am %s, counter:%s" % (self.name, counter)  
            mutex.release()  
 
if __name__ == "__main__":  
    for i in range(0, 100):  
        my_thread = MyThread()  
        my_thread.start()

这样一个线程获取到Lock的时候,这把锁就会进入Locked状态。其他线程就无法再获取,进入到block阻塞状态。

只有当前线程release这把锁的时候,这把锁重新进入到released状态。线程调度会随机挑选一个block的线程获得这把锁,重新进入running状态。

简单的互斥锁还存在一些死锁的问题,后续再讨论。

 

队列Queue

以上可以看到当多个线程需要共享资源或者数据的时候,会使得线程的使用变得复杂。线程有很多种方式来实现同步如条件变量,事件,锁。但是最佳实践是使用队列,队列使用更加简单,因为能够有效控制单个线程对资源的访问使得线程编程更加安全,而且实现的代码可读性更强。

一个使用队列控制资源的例子如下:

import threading 
import time
import Queue
import urllib2

hosts = ['http://www.baidu.com','http://www.sina.com.cn',
             'http://www.sohu.com','http://www.asiainfo.com',
         'http://www.taobao.com','http://www.126.com' ]
queue= Queue.Queue()

#populate queue with data
for host in hosts:
    queue.put(host)
    print host
print queue


#def Thread class
class QueueHandler(threading.Thread):
    def __init__(self,queue):
        threading.Thread.__init__(self)
        self.queue = queue

    def run(self):
        while True:
            host = self.queue.get()
            url = urllib2.urlopen(host)
            print 'thread is %s, visiting %s ,and the content======= %s'%(self.getName(),host,url.read(10))
            self.queue.task_done()    

start = time.time()
print start


# loading thread
def main():
    for i in range(5):
        t= QueueHandler(queue)
        t.setDaemon(True)
        t.start()


main()
#block the program
queue.join()

print ('time used:%s'%(time.time()-start))
posted @ 2014-11-01 22:59  shall we  阅读(438)  评论(0编辑  收藏  举报