python 爬虫 多线程

多线程介绍

多线程是为了同步完成多项任务,通过提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。

threading模块

threading模块是python中专门提供用来做多线程编程的模块,常用类是Thread。

import threading
import time
def coding():
      for x in renge(3):
            print('正在写代码%s'%x)
            time.sleep(1)

def drawing():
      for x in renge(3):
            print('正在画图%s'%x)
            time.sleep(1)

def main():
      t1 = threading.Thread(target=coding)
      t2 = threading.Thread(target=drawing)

if __name__ == '__main__':
      main()

查看线程数

是用threading.enumerate()函数可以看到当前线程的数量

查看当前线程的名字

使用threading.current_thread()可以看到当前线程信息

继承自threading.Thread类

为了让线程代码更好的封装,可以使用threading模块下的Thread类,继承自这个类,然后实现run()方法,线程就会自动运行run()方法

import threading
import time
class CodingThread(threading.Thread):
    def run(self):
		def coding():
      		for x in renge(3):
            	print('正在写代码%s'%x)
            	time.sleep(1)
class DrawThread(threading.Thread):
    def run(self):
		def drawing():
      		for x in renge(3):
            	print('正在画图%s'%x)
            	time.sleep(1)

def multy_thread():
      t1 = CodingThread()
      t2 = DrawThread()

	  t1.start()
	  t2.start()

if __name__ == '__main__':
      multy_thread()

锁机制

多线程都是在同一个进程中运行的,因此在进程中的全局变量所有的线程都是可共享的。这就照成了一个问题,因为线程执行的顺序是无序的,有可能会造成数据错误。为了解决以上问题,threading提供了一个Lock类,这个类可以在某个线程访问某一个变量的时候加锁,其他线程此时就进不来,知道当前线程处完后,把锁释放了,其他线程次能进来处理。

import threading

VALUE = 0

gLock = threading.Lock()

def add_value():
	global VALUE
	gLock.acquire()
	for x in range(1000000)
		VALUE +=1
	gLock.release()
	print('value:%d' %VALUE)

def main():
	for x in range(2):
		t = threading.Thread(target=add_value)
		t.start()

if __name__ == '__main__':
	main()

Lock版本生产者和消费者模式

生产者和消费者模式是多线程开发中经常见到的一种模式。生产者的线程专门用来生产一些数据,然后存放到一个中间的变量中。消费者再从这个中间的变量中取出数据进行消费。但是因为要使用中间变量,中间变量经常是一些全局变量,因此需要使用锁来保证数据完整性。

import threading
import random
import time

gMoney = 1000
gLock = threading.Lock()
gTotalTimes = 10
gTime = 0


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

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(1)


def main():
    for x in range(5):
        t = Product(name='生产者线程%d' % x)
        t.start()

    for x in range(3):
        t = Consumer(name='消费者线程%d' % x)
        t.start()


if __name__ == '__main__':
    main()

Queue线程安全队列

在线程中,访问一些全局变量,加锁是一个经常的过程。如果你是想把一些数据存储到某个队列中,那么 Python内置了一个线程安全的模块叫做 queue 模块。 Python中的queue模块中提供了同步的、线程安全以列类,包括FIFO(先进出)队列 Queue,LIFO(后入先出)队列 LifoQueue。这些队列都实现了锁原语(可以理解为原子操作,即么不做,更么都做完),能够在多程中直接使
用。可以使用队列来实现线程间的同步。相关的的数如下:

1.初始化 Queue( maxsize) 创建一个先进先出的队列。
2. gsize():返回队列的大小。
3. empty():判断队列是否为空。
4.full():判断队列是否满了。
5.get():从队列中取最后一个数据
6.put():将一个数据放到队列中。

你可能感兴趣的:(python 爬虫 多线程)