[python爬虫之路day13]:多线程——加速爬取数据

今天我们来介绍多线程。
进程里有很多目标,多线程的目的简言之就是加快进程,提高效率,多个操作同时进行。
下面来看代码:
一.初识

import time
import threading

###############单线程##############################
 def coding():
     for x in range(3):
         print("正在玩孙尚香%s"%x)
         time.sleep(1)
 def codis():
     for x in range(3):
         print("正在玩孙权%s" %x)
         time.sleep(1)
 def main():
     coding()
     codis()
 if __name__ == '__main__':
     main()
######3##############多线程###########################
def coding():
    for x in range(3):
        print("正在玩孙尚香%s" % threading.current_thread())#打印当前线程的名字
        time.sleep(1)
def codis():
    for x in range(3):
        print("正在玩孙权%s" %  threading.current_thread())#打印当前线程的名字
        time.sleep(1)


def main():
    t1=threading.Thread(target=coding)#创建线程
    t2=threading.Thread(target=codis)#创建线程
    t1.start()
    t2.start()
    print(threading.enumerate())#打印所有线程的名字
if __name__ == '__main__':
    main()

#二.使用thread类创建多线程

#二.使用thread类创建多线程
 class CodingThread(threading.Thread):
#     def run(self):
#         for x in range(3):
#             print("正在玩孙尚香%s" % threading.current_thread())  # 打印当前线程的名字
             time.sleep(1)
 class DrawThread(threading.Thread):
     def run(self):
         for x in range(3):
             print("正在玩孙权%s" % threading.current_thread())
             time.sleep(1)
 def main():
     t1=CodingThread()
     t2=DrawThread()
     t1.start()
     t2.start()
 if __name__ == '__main__':
     main()

三.多线程共享全局变量及锁机制

VALUE=0
gLook=threading.Lock()#锁机制1
def add_value():
    global VALUE
    gLook.acquire()#锁机制2
    for x in range(10000000):
        VALUE+=1
    gLook.release()#锁机制3
    print(VALUE)
def main():
    for x in range(2):
        t1=threading.Thread(target=add_value)
        t1.start()
if __name__ == '__main__':
    main()

四.多线程实例(生产者与消费者模式)
lock版本

import time
import threading
import random
gMoney=1000
gLock=threading.Lock()
gtotalTimes=10
gTime=0
class Producer(threading.Thread):
    def run(self):
        global gMoney
        global gTime
        while True:
            money=random.randint(100,1000)
            gLock.acquire()
            if gTime>=gtotalTimes:
                gLock.release()
                break
            gMoney+=money
            print('%s生产了%d元,剩余%d元钱'%(threading.current_thread(),money,gMoney))
            gTime+=1
            gLock.release()
            time.sleep(0.5)


class Consumer(threading.Thread):
    def run(self):
        global gMoney
        while True:
            money=random.randint(100,1000)
            gLock.acquire()
            if gMoney>=money:
                gMoney-=money
                print("%s消费了%d元,剩余%d元"%(threading.current_thread(),money,gMoney))
            else:
                if gTime>=gtotalTimes:
                    gLock.release()
                    break
                print('%s消费者准备消费%d元,剩余%d元,不足!'%(threading.current_thread(),money,gMoney))
            gLock.release()
            time.sleep(0.5)
def main():
    for x in range(3):
        t=Consumer(name='消费者线程%d'%x)
        t.start()
    for x in range(5):
        t=Producer(name='生产者线程%d'%x)
        t.start()

if __name__ == '__main__':
    main()

五.condition版本的消费者和生产者模式。
为了克服lock版本对cpu的损耗,我们采用threading.condition

1.acquire上锁
2.release解锁
3.wait:将该线程处于等待状态,并且会释放锁,可以被notify,notify_all唤醒。
4.notify通知某个在等待进程,默认为第一个。
5.notify_all:通知所有在等待的进程,并且notify_all和notify不会解锁,应该啊在release前调用。
下面来看代码:

import time
import threading
import random
gMoney=1000
gCondition=threading.Condition()
gtotalTimes=10
gTime=0
class Producer(threading.Thread):
    def run(self):
        global gMoney
        global gTime
        while True:
            money=random.randint(100,1000)
            gCondition.acquire()
            if gTime>=gtotalTimes:
                gCondition.release()
                break
            gMoney+=money
            print('%s生产了%d元,剩余%d元钱'%(threading.current_thread(),money,gMoney))
            gTime+=1
            gCondition.notify_all()#通知苏醒
            gCondition.release()
            time.sleep(0.5)


class Consumer(threading.Thread):
    def run(self):
        global gMoney
        while True:
            money=random.randint(100,1000)
            gCondition.acquire()
            while gMoney<money:
                if gTime>=gtotalTimes:
                    return
                print("%s准备消费%d元,剩余%d元,不足!"%(threading.current_thread(),money,gMoney))
                gCondition.wait()
            print('%s消费了%d元,剩余%d元'%(threading.current_thread(),money,gMoney))
            gCondition.release()
            time.sleep(0.5)
def main():
    for x in range(3):
        t=Consumer(name='消费者线程%d'%x)
        t.start()
    for x in range(5):
        t=Producer(name='生产者线程%d'%x)
        t.start()

if __name__ == '__main__':
    main()

Queue线程安全队列
加锁是个经常的过程,如果你想把一些数据存储到某个队列,python内置queue模块,其中Queue(先进先出),LiFoQueue(后进先出),可在多线程中使用,实现线程的同步。
1.q=Queue(3)#初始化创建一个先进先出队列。
2.qsize(),返回队列的大小。
3.empty()判断是否为空。
4.full() 判断是否满。
5.get() 按队列规则取出数据。
6.put(),将数据放入队列中。
下面看代码:

from queue import Queue
import time
import threading
q=Queue(4)
# print(q.qsize())
# print(q.empty())
# for x in range(4):
#     q.put(x)
#     print()
# print(q.full())
# for x in range(4):
#     print(q.get())
def set_value(q):
    index=0
    while True:
        q.put(index)
        index+=1
        time.sleep(3)
def get_valuee(q):
    while True:
        print(q.get())
def main():
    q=Queue(4)
    t1=threading.Thread(target=set_value,args=[q])
    t2=threading.Thread(target=get_valuee,args=[q])
    t1.start()
    t2.start()
if __name__ == '__main__':
    main()

你可能感兴趣的:(爬虫小白学习)