多线程的使用

多线程

前言

我看了不止一我的说多线程是鸡肋,可是就依照我我的以为多线程在一些小型的爬虫中仍是能够显著的提升速度的,相比多进程来讲应该仍是挺简单的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() 实际上意味着等到队列为空,再执行别的操做
相关文章
相关标签/搜索