我看了不止一个人说多线程是鸡肋,但是就依照我个人觉得多线程在一些小型的爬虫中还是可以显著的提高速度的,相比多进程来说应该还是挺简单的
继承threading.Thread模块是一个很好的一个选择,就像java中也是可以继承类和实现接口一样,这都是很好的选择,下面我们来看看具体如何使用
1234567891011121314151617181920212223242526 | 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() #释放线程锁Lockif __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中继承来实现多线程是一样的,就是一个对象只能是对应一个线程,并不能一个对象被多个线程共享,下面我们将会介绍另外的一种方式
上面我们说过继承的方式,但是我个人觉得对于一些比较小的爬虫还是有些繁琐的,因为总是需要重写run方法,现在我们来看看如何简化实现多线程
12345678910 | """这是一个简单的例子,其实也不是一个好的例子,但是为了演示方便就选用了,可以看出这里是直接调用了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() |
---|
从源代码可以看出队列是实现了锁原语的,因此可以使用队列实现线程的同步,这里的主要原理就不细说了,简单的说就是get和put等方法都实现了锁原语,就是当一个操作正在执行的时候其他的操作会阻塞等待 下面我自己写了一个使用两个线程实现同时入队和出队的程序
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 | import randomimport timefrom Queue import Queueclass 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() |
---|