python基础-21-进程与线程

进程与线程

一、什么叫多任务
多任务就是操作系统可以同时运行多个任务。比如你一边在用浏览器上网,一边在用慕课网官网学习,还一边在听音乐,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。
二、什么是进程
对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个word就启动了一个word进程,打开两个记事本就启动了两个记事本进程。大家可以在电脑上查看操作系统打开的进程,具体方法,以win8操作系统为例:在Win8传统桌面的任务栏上点击鼠标右键,选择任务管理器,即可快速打开Win8任务管理器如下:
在这里插入图片描述
打开之后,可以查看目前电脑都开启哪些应用进程和后台进程,以及每个进程分别所占用的计算机资源CPU、内存、磁盘等。
三、怎样的任务算一个进程当一个任务被开启后,操作系统会分配它所需的系统资源,包括内存,I/O和CPU等,如果系统资源
不够,则会出现系统崩溃,这样的任务可被称为进程。
四、在python中如何创建进程
使用的模块: multiprocessing 创建的方法: multiprocessing. Process(…)
五、什么是线程
线程(Thread)是操作系统最小的执行单元,进程至少由一个线程组成。如何调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间。有些进程还不止同时干一件事,比如微信,它可以同时进行语音、发文字、浏览信息等事情。简单理解:在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程。
六、怎样的任务算一个线程
进程被运行后算是一个线程,进程是不运行的,线程才会运行,而一个进程有多个线程就涉及到进程有多少可以被cpu单独调用的模块,这个调用的模块可以通过手动创建线程来建立。
七、在python中如何创建线程
使用的模块: threading
创建的方法: threading.Thread(…)
在这里插入图片描述

进程模块-multiprocessing

在这里插入图片描述

实例

普通运行

import time


def work_a():
    for i in range(10): # 循环0-9
        print(i,"a") # 打印循环
        time.sleep(1) # 等待1秒
def work_b():
    for i in range(10):
        print(i,"b")
        time.sleep(1)

if __name__ == "__main__" :
    start = time.time() # 开始时间
    work_a()
    work_b()
    print("耗时:",time.time() - start) # 完成时间减去开始时间

在这里插入图片描述

查看进程

import multiprocessing
import time
import os

def work_a():
    for i in range(10): # 循环0-9
        print(i,"a",os.getpid()) # 打印循环 #os.getpid()查看系统的pid进程
        time.sleep(1) # 等待1秒
def work_b():
    for i in range(10):
        print(i,"b",os.getpid())
        time.sleep(1)

if __name__ == "__main__" :
    start = time.time() # 开始时间
    work_a()
    work_b()
    print("耗时:",time.time() - start) # 完成时间减去开始时间
    print("parent pid is %s" % os.getpid())

如图我们能看见a和b都是在同一个进程
在这里插入图片描述

多进程

import multiprocessing
import time
import os

def work_a():
    for i in range(10): # 循环0-9
        print(i,"a",os.getpid()) # 打印循环 #os.getpid()查看系统的pid进程
        time.sleep(1) # 等待1秒
def work_b():
    for i in range(10):
        print(i,"b",os.getpid())
        time.sleep(1)

if __name__ == "__main__" :
    start = time.time() # 开始时间
    a_p = multiprocessing.Process(target=work_a)# 创建多进程
    a_p.start()
    work_b()
    print("耗时:",time.time() - start) # 完成时间减去开始时间
    print("parent pid is %s" % os.getpid())

在这里插入图片描述

子进程和主进程互不影响

import multiprocessing
import time
import os

def work_a():
    for i in range(10): # 循环0-9
        print(i,"a",os.getpid()) # 打印循环 #os.getpid()查看系统的pid进程
        time.sleep(1) # 等待1秒
def work_b():
    for i in range(10):
        print(i,"b",os.getpid())
        time.sleep(1)

if __name__ == "__main__" :
    start = time.time() # 主进程
    a_p = multiprocessing.Process(target=work_a)# 子进程1
    a_p.start() #子进程1执行
    b_p = multiprocessing.Process(target=work_b)  # 子进程2
    b_p.start() # 子进程2执行
    print("耗时:",time.time() - start) # 主进程
    print("parent pid is %s" % os.getpid()) # 主进程

在这里插入图片描述

进程阻塞

import multiprocessing
import time
import os

def work_a():
    for i in range(10): # 循环0-9
        print(i,"a",os.getpid()) # 打印循环 #os.getpid()查看系统的pid进程
        time.sleep(1) # 等待1秒
def work_b():
    for i in range(10):
        print(i,"b",os.getpid())
        time.sleep(1)

if __name__ == "__main__" :
    start = time.time() # 主进程
    a_p = multiprocessing.Process(target=work_a)# 子进程1
    # a_p.start() #子进程1执行
    b_p = multiprocessing.Process(target=work_b)  # 子进程2
    # b_p.start() # 子进程2执行

    for p in (a_p,b_p): # 所有子进程执行
        p.start()
    for p in (a_p,b_p): ## 执行完子进程后 在执行下面print的主进程
        p.join()  # 阻塞

    print("耗时:",time.time() - start) # 主进程
    print("parent pid is %s" % os.getpid()) # 主进程




在这里插入图片描述
– 子进程1有阻塞 子进程2无阻塞 就会出现 先执行 子进程1 然后主进程 最后子进程2

import multiprocessing
import time
import os

def work_a():
    for i in range(10): # 循环0-9
        print(i,"a",os.getpid()) # 打印循环 #os.getpid()查看系统的pid进程
        time.sleep(1) # 等待1秒
def work_b():
    for i in range(10):
        print(i,"b",os.getpid())
        time.sleep(1)

if __name__ == "__main__" :
    start = time.time() # 主进程
    a_p = multiprocessing.Process(target=work_a)# 子进程1
    a_p.start() #子进程1执行
    a_p.join() # 子进程阻塞
    b_p = multiprocessing.Process(target=work_b)  # 子进程2
    b_p.start() # 子进程2执行

    # for p in (a_p,b_p): # 所有子进程执行
    #     p.start()
    # for p in (a_p,b_p):
    #     p.join()  # 阻塞

    print("耗时:",time.time() - start) # 主进程
    print("parent pid is %s" % os.getpid()) # 主进程




在这里插入图片描述

进程池与进程锁

在这里插入图片描述

# -*- coding: utf-8 -*-
import os
import time
import multiprocessing

def work(count):
    print(count,os.getpid()) # 打印进程号
    time.sleep(5)

if __name__ == "__main__":
    pool = multiprocessing.Pool(5) # 进程池限制5个
    for i in range(20):
        pool.apply_async(func=work,args=(i,))
    time.sleep(20)

在这里插入图片描述

# -*- coding: utf-8 -*-
import os
import time
import multiprocessing

def work(count):
    print(count,os.getpid()) # 打印进程号
    time.sleep(5)

if __name__ == "__main__":
    pool = multiprocessing.Pool(5) # 进程池限制5个
    for i in range(20):
        pool.apply_async(func=work,args=(i,))
    pool.close()#关闭进程池,不再接受新的进程
    pool.join()#主进程阻塞等待子进程的退出
# -*- coding: utf-8 -*-
import os
import time
import multiprocessing

def work(count):
    print(count,os.getpid()) # 打印进程号
    time.sleep(5)
    return "result is %s,pid is %s"%(count,os.getpid())

if __name__ == "__main__":
    pool = multiprocessing.Pool(5) # 进程池限制5个
    results = []
    for i in range(20):
        result = pool.apply_async(func=work,args=(i,))
        results.append(result)

    for res in results:
        print(res.get())

在这里插入图片描述
在这里插入图片描述

# -*- coding: utf-8 -*-
import os
import time
import multiprocessing

def work(count,lock):
    lock.acquire()# 上锁
    print(count,os.getpid()) # 打印进程号
    time.sleep(5)
    lock.release() # 开锁

if __name__ == "__main__":
    pool = multiprocessing.Pool(5) # 进程池限制5个
    manager = multiprocessing.Manager() # 进程锁 同一时间只对一个进程生效
    lock = manager.Lock()
    for i in range(20):
        pool.apply_async(func=work,args=(i,lock))
    pool.close()#关闭进程池,不再接受新的进程
    pool.join()#主进程阻塞等待子进程的退出

在这里插入图片描述

线程

一、当多个线程运行时,可能会出现的问题及解决方案
通过线程执行的函数无法获取返回值——线程间如何通信:通过队列多个线程同时修改文件可能造成数据错错乱——线程间如何避免资源抢占:创建线程锁
线程数量太多可能会造成资源不足,甚至死机等情况——如何避免创建线程数量过多:创建线程池
二、通过对列通信来解决
在这里插入图片描述
三、创建线程锁
在线程代码中需要加上锁的地方写加锁代码,要释放锁的地方写解锁代码即可
使用模块: threading
如何加锁: threading.Lock().acquire()
如何解锁: threading.Lock().release()
四、创建线程池
首先写出创建线程池的方法,之后往线程池中放入线程即可
使用的模块: concurrent.futures

在这里插入图片描述

在这里插入图片描述
普通

import random
import time
import threading # 多线程模块
lists = ["python","django","tornado",
         "flask","bs5","requests"]
new_lists = []

def work():
    if len(lists) == 0 :
        return
    data = random.choice(lists) #从非空序列中随机选取一个数据并返回
    lists.remove(data)# remove() 函数可以删除列表中的指定元素
    new_data = "%s_new"% data # 重命名
    new_lists.append(new_data) # 追加到新列表
    time.sleep(1) # 等待1秒

if __name__=="__main__":
    start = time.time() # 开始时间
    for i in range(len(lists)): # 按照列表的长度循环运行work函数
        work()
    print("old list:",lists)  # 打印lists列表内容
    print("new list:",new_lists) # 打印new list列表内容
    print("time is %s"%(time.time()-start)) # 耗时

在这里插入图片描述
线程实例

import random
import time
import threading # 多线程模块
lists = ["python","django","tornado",
         "flask","bs5","requests"]
new_lists = []

def work():
    if len(lists) == 0 :
        return
    data = random.choice(lists) #从非空序列中随机选取一个数据并返回
    lists.remove(data)# remove() 函数可以删除列表中的指定元素
    new_data = "%s_new"% data # 重命名
    new_lists.append(new_data) # 追加到新列表
    time.sleep(1) # 等待1秒

if __name__=="__main__":
    start = time.time() # 开始时间
    t_list = []
    for i in range(len(lists)): # 按照列表的长度循环运行work函数
        t = threading.Thread(target=work) # 实例化一个线程
        t_list.append(t)
        t.start() # 启动线程
    for t in t_list:
        t.join()# 阻塞 运行完子程序后在运行下面的打印

    print("old list:",lists)  # 打印lists列表内容
    print("new list:",new_lists) # 打印new list列表内容
    print("time is %s"%(time.time()-start)) # 耗时

在这里插入图片描述
在这里插入图片描述

线程池

在这里插入图片描述
在这里插入图片描述

import time
import threading
import concurrent
from concurrent.futures import ThreadPoolExecutor


lock = threading.Lock() # 实例化一个线程锁

def work(i):
    # lock.acquire()
    print(i)
    time.sleep(1)
    # lock.release()


if __name__=="__main__":
    t  = ThreadPoolExecutor(2) # 线程池2个线程
    for i in range(20):
        t.submit(work,(i,))

在这里插入图片描述
线程锁

import time
import threading
import concurrent
from concurrent.futures import ThreadPoolExecutor


lock = threading.Lock() # 实例化一个线程锁

def work(i):
    lock.acquire()
    print(i)
    time.sleep(1)
    lock.release()


if __name__=="__main__":
    t  = ThreadPoolExecutor(2) # 线程池2个线程
    for i in range(20):
        t.submit(work,(i,))

在这里插入图片描述

异步

异步相对同步而言,同步意味着有序,异步意味着无序,正因为异步的无序,使得各个程序间的协调成为一大难题,异步编程就是解决这一难题的编程,它是以进程、线程、协程、函数/方法作为执行任务程序的基本单位,结合回调、事件循环、信号量等机制,以提高程序整体执行效率和并发能力的编程方式
Python中如何实现异步
方法一:
如何定义一个异步,使用关键字: async
在一个异步程序里,如何调用另一个异步,使用关键字: await
如何调用一个异步函数,使用模块: asyncio
在这里插入图片描述
同步执行实例

import time

def a():
    for i in range(10):
        print(i,"我是A")
        time.sleep(1)# 等待时间
    return "a function"

def b():
    for i in range(10):
        print(i,"我是B")
        time.sleep(1)
    return "b function"

if __name__=="__main__":
    start = time.time()
    a()
    b()
    print("耗时%s"%(time.time()-start))

在这里插入图片描述
异步执行实例

import time
import asyncio

async def a():
    for i in range(10):
        print(i,"我是A")
        await asyncio.sleep(1) #  time.sleep是cpu级别的阻塞我们需要更改asyncio.sleep
    return "a function"

async def b():
    for i in range(10):
        print(i,"我是B")
        await asyncio.sleep(1)
    return "b function"

async def main():
    result = await asyncio.gather(
        a(),
        b()
    )
    print(result)

if __name__=="__main__":
    start = time.time()
    asyncio.run(main())
    print("耗时%s"%(time.time()-start))

在这里插入图片描述
在这里插入图片描述

import time
import gevent

def gevent_a():
    for i in range(10):
        print(i,"我是A")
        gevent.sleep(1) # 阻塞
    return "我是gevent a result"

def gevent_b():
    for i in range(10):
        print(i,"我是B")
        gevent.sleep(1)
    return "我是gevent b result"


if __name__=="__main__":
    start = time.time()
    g_a = gevent.spawn(gevent_a)
    g_b = gevent.spawn(gevent_b)
    gevent_list = [g_a,g_b]
    result = gevent.joinall(gevent_list)
    print(result)
    print("耗时%s"%(time.time()-start))

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值