python基础(十五):并发编程、多线程

概述

  • 非并发
    程序由单个步骤序列构成,包含独立子任务的程序执行性能低
  • 并发
    异步高效,分解子任务,简化流程与逻辑
  • 进程
    一个程序的执行实例,有自己地址空间、内存、数据栈、辅助数据
  • 线程
    进程内可被并行激活的控制流,共享相同上下文
    便于信息共享通信,但访问顺序差异导致结果不一致。
  • 全局解释器锁GIL(Global Interpreter Lock)
    代码由虚拟机(解释主循环控制),主循环同时只能有一个控制线程执行

多线程

_thread模块

特点

没有控制进程结束机制
只有一个同步原语(锁)
功能少于threading模块

.start_new_thread

.start_new_thread(function,args,**kwargs=None)开始进程

import time
'''单线程例子'''
def worker(n):
    print(f'函数执行开始于:{time.ctime()}')
    time.sleep(n)

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

def main():
    print(f'主函数执行开始于:{time.ctime()}')
    worker(4)
    worker(2)
    print(f'主函数执行结束于:{time.ctime()}')

if __name__ == '__main__':
    main()

在这里插入图片描述

#多线程

import time
import _thread


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

    time.sleep(n)

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

def main():
    print(f'主函数执行开始于:{time.ctime()}')
    #执行函数,执行函数参数,参数以元组形式
    _thread.start_new_thread(worker,(4,))
    _thread.start_new_thread(worker,(2,))

    time.sleep(5)
    print(f'主函数执行结束于:{time.ctime()}')

if __name__ == '__main__':
    main()

在这里插入图片描述

threading模块

.Thread 线程类

  • 构造
    .Thread(target=目标函数,args=(参数,))
    自定义Thread派生类,重写run方法逻辑
  • .start() 启动线程
  • .join() 要求主线程等待执行
#threading多线程
import time
import threading

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

def main():
    print(f'[主函数执行开始于:{time.ctime()}')
    #统一发号指令
    #线程的实例先不执行放在数组中
    threads = []
    #创建group-none,target当前线程执行哪个函数
    t1 = threading.Thread(target=worker,args=(4,))
    threads.append(t1)

    t2 = threading.Thread(target=worker,args=(2,))
    threads.append(t2)

    for t in threads:
        t.start()

    for t in threads:
        t.join()

    print(f'[主函数执行结束于:{time.ctime()}\n')

if __name__ == '__main__':
    main()

在这里插入图片描述

.current_thread() 获取当前线程

#threading多线程thread有编号
import time
import threading

def worker(n):
    print('{} 函数执行开始于:{}'.format(threading.current_thread().name,time.ctime()))
    time.sleep(n)
    print(f'{threading.current_thread().name}函数执行结束于:{time.ctime()}')

def main():
    print(f'[主函数执行开始于:{time.ctime()}')
    #统一发号指令
    #线程的实例先不执行放在数组中
    threads = []
    #创建group-none,target当前线程执行哪个函数
    t1 = threading.Thread(target=worker,args=(4,))
    threads.append(t1)

    t2 = threading.Thread(target=worker,args=(2,))
    threads.append(t2)

    for t in threads:
        t.start()

    for t in threads:
        t.join()

    print(f'[主函数执行结束于:{time.ctime()}\n')

if __name__ == '__main__':
    main()

在这里插入图片描述

#thread类派生类

import time
import threading

def worker(n):
    print('{} 函数执行开始于:{}'.format(threading.current_thread().name,time.ctime()))
    time.sleep(n)
    print(f'{threading.current_thread().name}函数执行结束于:{time.ctime()}')

class MyThread(threading.Thread):
    def __init__(self,func,args):
        threading.Thread.__init__(self)
        self.func = func
        self.args = args
    def run(self):
        #执行自己的函数,传递元组需要解包
        self.func(*self.args)

def main():
    print(f'[主函数执行开始于:{time.ctime()}')
    #统一发号指令
    #线程的实例先不执行放在数组中
    threads = []

    t1 = MyThread(worker,(4,))
    threads.append(t1)

    t2 = MyThread(worker,(2,))
    threads.append(t2)

    for t in threads:
        t.start()

    for t in threads:
        t.join()

    print(f'[主函数执行结束于:{time.ctime()}\n')

if __name__ == '__main__':
    main()

在这里插入图片描述

threading.Lock 同步原语:锁

.acquire() 获得
.release() 释放
支持上下文操作 with lock:

import threading
import time
'''同步原语——锁——引入'''


eggs = []

def put_egg(n,lst):
    for i in range(1,n+1):
        lst.append(i)

def main():
    threads = []
    #创建三个线程
    for i in range(3):
        #每个线程放5个鸡蛋
        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()

输出

D:\python\python.exe F:/teacher/pythonbasetry/day12/mt——4.py
[1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
Process finished with exit code 0

存在弊端:顺序错乱

import threading
import time
import random
'''同步原语——锁——random'''


eggs = []

def put_egg(n,lst):
    for i in range(1,n+1):
        time.sleep(random.randint(0,2))
        lst.append(i)

def main():
    threads = []
    #创建三个线程
    for i in range(3):
        #每个线程放5个鸡蛋
        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()

D:\python\python.exe F:/teacher/pythonbasetry/day12/mt——4.py
[1, 2, 3, 1, 1, 4, 2, 3, 4, 5, 2, 3, 4, 5, 5]
Process finished with exit code 0

队列

queue 模块

Queue FIFO

.Queue(maxsize=0) 构造实例
.put(item,block=True,timeout=None)放入数据项
.get(block=True,timeout=None) 获取数据项
.task_done() 声明当前队列任务处理完毕
.join() 队列所有项处理完毕前阻塞

LifoQueue LIFO——栈

PriorityQueue 优先队列

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

在这里插入图片描述

mutiprocessing 模块

充分运用多核、多cpu计算能力,适用于计算密集型任务

'''多进程'''
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()}')

    process =[]
    p1 = multiprocessing.Process(target=func,args=(4,))
    process.append(p1)

    p2 = multiprocessing.Process(target=func,args=(2,))
    process.append(p2)

    for p in process:
        p.start()
    for p in process:
        p.join()



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

if __name__=='__main__':
    main()

在这里插入图片描述

concurrent.futures 模块

ThreadPoolExecutor

ProcessPoolExecutor

import time
import concurrent.futures

numbers = list(range(1,11))

def count(n):
    for i in range(10000000):
        i +=1
    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()}')

# 线程池
def threading_execution():
    start_time = time.clock()
    #线程池中最多线程5个
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        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:
        for i in numbers:
            executor.submit(worker,i)

    print(f'进程池执行花费时间:{time.clock()-start_time} 秒')

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

process_execution
在这里插入图片描述
threading_execution
在这里插入图片描述
sequetial_execution
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值