多線程的使用

多線程

前言

我看了不止一我的說多線程是雞肋,可是就依照我我的以爲多線程在一些小型的爬蟲中仍是能夠顯著的提升速度的,相比多進程來講應該仍是挺簡單的java

使用多線程

繼承threading.Thread

繼承threading.Thread模塊是一個很好的一個選擇,就像java中也是能夠繼承類和實現接口同樣,這都是很好的選擇,下面咱們來看看具體如何使用python

class Mythread(threading.Thread):
    def __init__(self,threadID,name,counter):
        threading.Thread.__init__(self)    #首先須要先保留原來threading.Thread中的初始化函數
        self.threadID=threadID      #重命名線程的ID
        self.name=name              #線程的名字
        self.counter=counter        #線程的數量

    def run(self):
        lock.acquire()      #獲取線程鎖Lock
        for i in range(10):
            print "線程"+self.name+"開始運行"
        lock.release()      #釋放線程鎖Lock
if __name__ == '__main__':
    lock=threading.Lock()     
    t1=Mythread(0,"thread-1",3)
    t2=Mythread(1,"thread-2",3)

    t1.start()
    t2.start()

    threads=[]
    threads.append(t1)
    threads.append(t2)
    for t in threads:
        t.join()                #阻塞主線程,直至線程運行完畢才運行main線程的語句
    print "線程運行結束"

須要注意的是,這種繼承的方式有一個缺點,這個和java中繼承來實現多線程是同樣的,就是一個對象只能是對應一個線程,並不能一個對象被多個線程共享,下面咱們將會介紹另外的一種方式多線程

直接調用threading.Thread

上面咱們說過繼承的方式,可是我我的以爲對於一些比較小的爬蟲仍是有些繁瑣的,由於老是須要重寫run方法,如今咱們來看看如何簡化實現多線程app

"""
這是一個簡單的例子,其實也不是一個好的例子,可是爲了演示方便就選用了,能夠看出這裏是直接調用
了func函數,而後變成多個線程同時並行,其中target是要調用的方法(沒有括號),args是方法調用須要傳入的參數
其實這個仍是和上面的繼承比較類似的
"""
def func(name,age):
    for i in range(10):
        print name+"的年齡爲:"+str(age)       
t=threading.Thread(target=func,args=["陳加兵",22])
t.start()

Thread對象的相關方法

  • start() 啓動線程
  • join([timeout]) 設置阻塞線程,timeout是可選的參數,表示阻塞的時間,若是沒有就是當此線程運行結束纔開始運行下一個線程
  • run() 線程活動的方法
  • getName() 獲取線程名稱
  • setName() 設置線程的名稱
  • isAlive() 判斷線程是否還活着
  • isDaemon() 判斷是不是守護線程
  • setDaemon() 設置爲守護線程,守護線程就是當主線程運行完後,這個線程也會隨着主線程的結束而結束

共享隊列

從源代碼能夠看出隊列是實現了鎖原語的,所以可使用隊列實現線程的同步,這裏的主要原理就不細說了,簡單的說就是get和put等方法都實現了鎖原語,就是當一個操做正在執行的時候其餘的操做會阻塞等待dom

下面我本身寫了一個使用兩個線程實現同時入隊和出隊的程序函數

import random
import time
from Queue import Queue
class myThread(threading.Thread):
    def __init__(self,threadID,name,counter,q,flag):
        """
        threadID是線程的ID
        name是線程的名稱
        q是先進先出隊列
        flag是用來調用get和put的標誌
        """
        threading.Thread.__init__(self)
        self.name=name
        self.threadID=threadID
        self.counter=counter
        self.q=q
        self.flag=flag   
        
    def run(self):
        """
        當flag爲1時就調用put方法,不然調用get
        """
        if self.flag==1:
            self.put()
        else:
            self.get()
            

    def put(self):
        while True:
            self.q.put(random.randint(0,10))
    
    def get(self):
        while True:
            if not self.q.empty():
                print self.q.get()
            
        
            

            
if __name__=="__main__":

    threadLock=threading.Lock()
    q=Queue()
    
    t1=myThread(1,"Thread-1",1,q,1)
    t2=myThread(2,"Thread-2",2,q,2)
    
    threads=[]
    
    threads.append(t1)
    threads.append(t2)
    
    t1.start()
    t2.start()

Queue相關的一些方法

  1. Queue.qsize() 返回隊列的大小
  2. Queue.empty() 若是隊列爲空,返回True,反之False
  3. Queue.full() 若是隊列滿了,返回True,反之False
  4. Queue.full 與 maxsize 大小對應
  5. Queue.get([block[, timeout]])獲取隊列,timeout等待時間
  6. Queue.get_nowait() 至關Queue.get(False)
  7. Queue.put(item) 寫入隊列,timeout等待時間
  8. Queue.put_nowait(item) 至關Queue.put(item, False)
  9. Queue.task_done() 在完成一項工做以後, Queue.task_done()函數向任務已經完成的隊列發送一個信號
  10. Queue.join() 實際上意味着等到隊列爲空,再執行別的操做
相關文章
相關標籤/搜索