python学习之多线程使用
多线程的作用就不做赘述,那么我们来探究一下python的多线程的使用方法,以及线程之间如何进行协作
多线程实现的方式
1.继承方式的多线程
import threading
class Hello(threading.Thread):
'''
继承 threading.Thread 重新其run()方法
就可以实现多线程运行
但是实际上需要使用start方法才会调用OS的创建新线程步骤 并且执行run()方法
若直接调用run() 则没有进行向OS申请创建线程 由当前线程进行执行
'''
def __init__(self, name):
super(Hello, self).__init__(name=name)
self.name = name
def run(self):
print("%s执行" % threading.current_thread().name)
if __name__ == "__main__":
print("%s执行" % threading.current_thread().name)
t = Hello(name="t_1")
t.start()
# t.run()
运行结果(使用tstart()):
MainThread执行
t_1执行
运行结果(使用t.run())
MainThread执行
MainThread执行
2.使用方法调用多线程(python3.0已经不支持使用)
import time import thread def timer(no, interval): cnt = 0 while cnt<10: print 'Thread:(%d) Time:%s\n'%(no, time.ctime()) time.sleep(interval) cnt+=1 thread.exit_thread() def test(): #Use thread.start_new_thread() to create 2 new threads thread.start_new_thread(timer, (1,1)) thread.start_new_thread(timer, (2,2)) if __name__=='__main__': test()
简单的线程协作
join()
一个栗子,主线程等待子线程运行完毕后再向下执行
import threading import time class Hello(threading.Thread): ''' 继承 threading.Thread 重新其run()方法 就可以实现多线程运行 但是实际上需要使用start方法才会调用OS的创建新线程步骤 并且执行run()方法 若直接调用run() 则没有进行向OS申请创建线程 由当前线程进行执行 ''' def __init__(self, name): super(Hello, self).__init__(name=name) self.name = name def run(self): print("%s开始执行" % threading.current_thread().name) time.sleep(1) print("%s结束执行" % threading.current_thread().name) if __name__ == "__main__": print("%s执行" % threading.current_thread().name) t = Hello(name="t_1") t.start() t.join() print("主线程结束")
结果:
MainThread执行
t_1开始执行
t_1结束执行
主线程结束
线程之间的协作,Lock和Condition。
一个简单的生产者 消费者模型:
from threading import Thread, Lock, Condition import time product = [] class Producter(Thread): def __init__(self, name, maxinum, lock, condition): super(Producter, self).__init__(name=name) self.maxinum = maxinum self.lock = lock self.condition = condition def run(self): for i in range(0, 30): product_name = 'product-%d' % i self.product_method(product_name) time.sleep(0.1) def product_method(self, name): ''' 生产商品 ''' lock: Lock = self.lock condition: Condition = self.condition lock.acquire() try: global product while len(product) == self.maxinum: condition.wait() print("仓库已经满了,停下生产!!!") product.append(name) condition.notify_all() finally: lock.release() class Consumer(Thread): def __init__(self, name, lock, condition): super(Consumer, self).__init__(name=name) self.lock = lock self.condition = condition def run(self): for i in range(0, 30): product_name = self.getProduct() print(f"消费者:{self.name},消费产品:{product_name}") time.sleep(0.1) def getProduct(self): lock: Lock = self.lock condition: Condition = self.condition lock.acquire() try: ''' 生产商品 ''' global product while len(product) == 0: condition.wait() print("仓库已经空了,停下消费!!!") condition.notify_all() return product.pop() finally: lock.release() if "__main__" == __name__: lock = Lock() condition = Condition(lock) p = Producter('product_1', 3, lock, condition) c = Consumer('consumer_1', lock, condition) p.start() c.start() p.join() c.join() print("END!!!!")
简单的生产30个产品 消费30个产品,生产超过仓库最大容量,则停下生产,仓库中没有任何商品,则停下消费。
另外一个栗子,多线程下载器
from threading import Thread, Lock, Condition import requests import datetime import os import string import random import time ''' 工作线程 ''' workers = [] ''' 任务池 ''' tasks = [] class MultiDownloader(): def __init__(self, num): lock = Lock() condition = Condition(lock) self.lock = lock self.condition = condition self.num = num self.__initWorker(num, lock, condition) def __initWorker(self, num, lock, condition): for i in range(0, num): tempName = 'worker-%d' % i print(tempName) temp = DownWorker(tempName, lock, condition) workers.append(temp) temp.start() def addTask(self, path, url): lock: Lock = self.lock condition: Condition = self.condition try: lock.acquire() task = DownTask(path, url) tasks.append(task) condition.notify_all() finally: lock.release() class DownWorker(Thread): def __init__(self, name, lock, condition): super(DownWorker, self).__init__(name=name) self.lock = lock self.condition = condition def run(self): print(f"线程:{self.name},开始运行!!!") while True: self.work() time.sleep(0.01) def work(self): lock: Lock = self.lock condition: Condition = self.condition try: lock.acquire() while len(tasks) == 0: condition.wait() task: DownTask = tasks.pop() print(f"线程:{self.name},准备执行下载任务:{task.url}") task.download() condition.notify_all() finally: lock.release() class DownTask: def __init__(self, path, url): self.path = path self.url = url def download(self): start_time = datetime.datetime.now() url = self.url response = requests.get(url) photo_path = self.path + os.sep + self.random_str(8) + ".png" if response.status_code == 200: with open(photo_path, "wb") as f: f.write(response.content) print(f"Downloaded url: {url} ,locate save path:{photo_path}") end_time = datetime.datetime.now() print(f"总耗时:{(end_time - start_time).seconds} 秒", ) def random_str(cls, lenth): result: string = "" while len(result) < lenth: result += random.choice('abcdefghijklmnopqrstuvwxyz') return result if __name__ == "__main__": downloader = MultiDownloader(3) urls = ["https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF", "https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF", "https://t7.baidu.com/it/u=4036010509,3445021118&fm=193&f=GIF", "https://t7.baidu.com/it/u=963301259,1982396977&fm=193&f=GIF", "https://t7.baidu.com/it/u=1575628574,1150213623&fm=193&f=GIF", "https://t7.baidu.com/it/u=737555197,308540855&fm=193&f=GIF", "https://t7.baidu.com/it/u=91673060,7145840&fm=193&f=GIF", "https://t7.baidu.com/it/u=2291349828,4144427007&fm=193&f=GIF"] path = "C:\\Users\\tangyuan\\Desktop\\jar" for temp in urls: downloader.addTask(path, temp)
使用方法和java的ReentLock+Condition类似
浙公网安备 33010602011771号