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类似

posted @ 2024-04-02 15:15  琼尼-沃克  阅读(153)  评论(0)    收藏  举报