python并发编程

在这里插入图片描述
_thread模块实现多线程(由于功能不全,不推荐使用)

import _thread
import time

def worktime(n):
    print(f'函数执行开始于{time.ctime()}')
    time.sleep(n)
    print(f'函数执行结束于{time.ctime()}')

def main():
    print(f'【主函数】执行开始于{time.ctime()}')
    _thread.start_new_thread(worktime,(2,))
    _thread.start_new_thread(worktime,(4,))
    time.sleep(5) #由于thread功能不全,需要设置睡眠时间,来等待线程执行完毕
    print(f'【主函数】执行结束于{time.ctime()}')


if __name__ == '__main__':
    main()

结论:实现多线程开始执行,于逐一执行比较,总体所用时间减少。

threading模块
threading.Thread() 实现多线程:

import threading
import time

def worktime(n):
    print(f'{threading.current_thread()}函数执行开始于{time.ctime()}')#可以通过threading.current_thread获取当前正在执行 线程名称
    time.sleep(n)
    print(f'{threading.current_thread()}函数执行结束于{time.ctime()}')

def main():
    print(f'【主函数】执行开始于{time.ctime()}')

    threads = [] #首先建立一个空列表,之后把线程加入列表,然后通过遍历列表执行线程
    t1 = threading.Thread(target=worktime,args=(2,)) #创建第一个线程
    threads.append(t1) #将线程加入列表

    t2 = threading.Thread(target=worktime, args=(4,))  # 创建第二个线程
    threads.append(t2)  # 将线程加入列表

    for t in threads:#通过遍历列表来执行所有线程
        t.start()#线程执行命令

    for t in threads:
         t.join()#让主函数等所有线程执行完毕再结束

    print(f'【主函数】执行结束于{time.ctime()}')


if __name__ == '__main__':
    main()

结论:实现多线程开始执行,于逐一执行比较,总体所用时间减少。

threading.Thread()派生(创建类) 实现多线程:

import threading
import time

def worktime(n):
    print(f'{threading.current_thread()}函数执行开始于{time.ctime()}')#可以通过threading.current_thread获取当前正在执行 线程名称
    time.sleep(n)
    print(f'{threading.current_thread()}函数执行结束于{time.ctime()}')

class MyThread(threading.Thread):#创建一个类,继承threading.Thread
    def __init__(self,func,args):#指定委托函数是什么,参数是什么
        threading.Thread.__init__(self)#想让threading.Thread执行它自己的init构造函数
        self.func = func
        self.args = args

    def run(self):
        self.func(*self.args)#由于参数是元组形式,传入时需要用*解剖

def main():
    print(f'【主函数】执行开始于{time.ctime()}')

    threads = [] #首先建立一个空列表,之后把线程加入列表,然后通过遍历列表执行线程
    t1 = MyThread(worktime,(2,))#通过类创建第一个线程
    threads.append(t1) #将线程加入列表

    t2 = MyThread(worktime,(4,)) #通过类创建第二个线程
    threads.append(t2)  # 将线程加入列表

    for t in threads:#通过遍历列表来执行所有线程
        t.start()#线程执行命令

    for t in threads:
         t.join()#让主函数等所有线程执行完毕再结束

    print(f'【主函数】执行结束于{time.ctime()}')


if __name__ == '__main__':
    main()

结论:实现多线程开始执行,于逐一执行比较,总体所用时间减少。

同步原语:锁(避免多线程同时执行时导致结果不一致)

import threading
import time
import random


eggs = []
lock = threading.Lock()#同步原语:锁

def put_egg(n,list):
    lock.acquire()#每个线程执行时,获得锁,并且锁上,避免别的线程执行结果的干扰
    for i in range(1,n+1):
        time.sleep(random.randint(0,2))#用睡眠时间表示真实情况下每个线程执行需要的时间
        list.append(i)
    lock.release()#每个线程执行结束之后,要把锁打开

def main():
    threads = []

    for i in range(3):
        t = threading.Thread(target=put_egg,args=(5,eggs))
        threads.append(t)

    for t in threads:
        t.start()

    for t in  threads:
        t.join()

    print(eggs)

if __name__ == '__main__':
    main()

结论:通过锁进行多线程运行,并未对期待结果产生影响。

Queue队列
FIFO queue:(先进先出队列)

import threading
import queue
import time
import random



def producer(data_queue):#依次将随机产生的数字放入队列
    for i in range(5):
        time.sleep(0.5)#生产者每隔半秒钟向队列中放入一个随机数
        item = random.randint(1,100)
        data_queue.put(item)
        print(f'{threading.current_thread().name}在队列中放入数据{item}')

def consumer(data_queue):#从队列中取出数据
    while True:
        try:
            item = data_queue.get(timeout = 3)#设置一个超时功能,设为3秒
            print(f'{threading.current_thread().name}从队列中移除了数据{item}')
        except queue.Empty:#捕获一个异常信息,当队列空了,没有数据可取时,跳出循环
            break
        else:
            data_queue.task_done()#声明正常情况下,当前数据项已经处理完毕



def main():
    q = queue.Queue()#构造接收,处理对象的队列

    threads = []
    p = threading.Thread(target=producer,args=(q,))#创建生产者线程
    p.start()#执行生产者线程

    for t in range(2):#创建两个消费者线程
        c = threading.Thread(target=consumer,args=(q,))
        threads.append(c)

    for t in threads:
        t.start()#执行消费者线程

    for t in threads:
        t.join()#让主线程等待消费者线程执行完毕

    q.join()#让主线程等待生产者线程执行完毕

if __name__ == '__main__':
    main()

结论:符合先进先出队列特征。

multiprocess多线程模块:(适用于计算密集型任务,使用方法于threading类似)

import multiprocessing
import time



def func(n):
    print(f'{multiprocessing.current_process().name}开始执行于{time.ctime()}')
    time.sleep(n)
    print(f'{multiprocessing.current_process().name}结束执行于{time.ctime()}')


def main():
    print(f'主函数执行于{time.ctime()}')

    processes = []
    p1 = multiprocessing.Process(target=func,args=(2,))
    processes.append(p1)

    p2 = multiprocessing.Process(target=func, args=(4,))
    processes.append(p2)

    for p in processes:
        p.start()

    for p in processes:
        p.join()

    print(f'主函数结束于{time.ctime()}')



if __name__ == '__main__':
    main()

concurrent.futures 模块

import concurrent.futures
import time



numbers = list(range(1,11))#在列表中生成数字1-10

def count(n):
    for i in range(10000000):
        i += i
    return i * n


def worker(x):
    result = count(x)
    print(f'数字:{x} 的计算结果是:{result}')

#顺序执行,不使用多进程或者多线程
def sequential_execution():
    start_time = time.clock()
    for i in numbers:
        worker(i)
    print(f'顺序执行花费时间为:{time.clock() - start_time}秒')

#线程池执行
def threading_execution():
    start_time = time.clock()
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:#使用concurrent.futures.ThreadPoolExecutor创建线程,并设置最大线程数为5
        for i in numbers:
            executor.submit(worker,i)#使用执行器来执行函数
    print(f'顺序执行花费时间为:{time.clock() - start_time}秒')


#进程池执行
def process_execution():
    start_time = time.clock()
    with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:  #使用concurrent.futures.ProcessPoolExecutor创建进程,并设置最大线程数为5
        for i in numbers:
            executor.submit(worker, i)#使用执行器来执行函数
    print(f'顺序执行花费时间为:{time.clock() - start_time}秒')


if __name__ == '__main__':
    sequential_execution()
    #threading_execution()
    #process_execution()

结论:依次执行任务每种方法后比较其所花费时间。得知,计算密集型任务首选多进程,IO密集型任务首选多线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值