多任务-进程-线程--0515

多任务

①、什么是多任务
多任务就是同时运行多个应用程序。例如QQ,微信等等同时运行。

②、电脑实现多任务的原理
CPU在多个应用程序间快速切换运行,让人感觉不到停顿。

③、python中实现多任务的3中方式
进程,线程,协程

一、进程

1、什么是进程
运行起来的程序,就是进程。不运行的时候,就是程序。程序只有一个,进程可以有多个。

2、创建多进程----需要导入multiprocessing多进程模块

from multiprocessing import Process
import time
def sing():
    for i in range(3):
        print("---正在唱歌---",i)
        time.sleep(1)
def dance():
    for i in range(3):
        print("---正在跳舞---",i)
        time.sleep(1)
def main():
    p1 = Process(target = sing)  #创建进程p1,执行sing函数
    p2 = Process(target = dance) #创建进程p2,执行dance函数
    p1.start()  #开始执行进程p1
    p2.start()  #开始执行进程p2

if __name__ == '__main__': #开启2个子进程p1,p2
    main()

3、多进程之间相互独立

from multiprocessing import Process
a = 1
def func1():
    global a
    a += 1
    print("func1:",a)
def func2():
    global a
    a += 1
    print("func2:",a)
def main():
    p1 = Process(target = func1)
    p2 = Process(target = func2)
    p1.start()
    p2.start()
if __name__ == '__main__':
    main()

4、进程的状态
程序运行过程中,由于被操作系统的调度算法控制,程序会进入几个状态:就绪,运行,阻塞。
①、就绪(Ready)状态
当进程已分配到除CPU以外所有的必要资源,只要分配到CPU便可立即执行,这时的进程状态称之为就绪状态。

②、执行/运行(Running)状态
当进程已分配到CPU,其程序正在运行,此时的进程状态称之为执行/运行状态。

③、阻塞(Blocked)状态
正在执行的进程,由于某个事件发生而无法执行时,便放弃CPU时而停止时,此时的进程状态称之为阻塞状态。
例如等待I/O完成,申请缓冲区不能满足,等到信号等等。

from multiprocessing import Process
def func1():
    print("func1")
def func2():
    print("func2")
def main():
    p1 = Process(target = func1)
    x = input("请输入:")         #程序运行到这,等待输入,进入阻塞状态
    p2 = Process(target = func2)
    p1.start()
    p2.start()
if __name__ == '__main__':
    main()

5、进程之间通讯----需要创建Queue队列类
两个进程通讯,就是一个子进程往Queue队列中写入数据,另一个子进程从Queue中取出数据。这就实现了进程间的通讯了。

①、创建Queue(maxsize)队列对象,maxsize表示队列中允许的最大项数。如果无此参数,则无数量大小限制。
②、args=(),给函数传递参数

from multiprocessing import Process
def func1(a,b):
    print("func1:",a + b)
def func2(name):
    print("func2:",name)
def main():
    p1 = Process(target = func1,args = (1,2))
    p2 = Process(target = func2,args = ("张三",))
    p1.start()
    p2.start()
if __name__ == '__main__':
    main()

③、put(),向队列中存放数据

from multiprocessing import Queue
q = Queue(2)    #创建队列,队列最大项为2
q.put("消息1")
print(q)        #<multiprocessing.queues.Queue object at 0x0000000001D87470>,返回一个队列对象
q.put("消息2")
print(q)        #<multiprocessing.queues.Queue object at 0x0000000001D87470>,返回一个队列对象
q.put("消息3") #超出队列最大项,无法再输入
print(q)       #超出队列最大项,无法再输入

④、qsize(),获取队列中数据的数量

from multiprocessing import Queue
q = Queue(2)
print(q.qsize())  #0,还未放入数据,数量为0
q.put("消息1")
print(q.qsize())  #1
q.put("消息2")
print(q.qsize())  #2

⑤、full(),判断队列中是否存放满了

from multiprocessing import Queue
q = Queue(2)
print(q.full())  #False,还未写入数据,未满
q.put("消息1")
print(q.full())  #False,写入一条数据,未满
q.put("消息2")
print(q.full())  #True,已经写入两条数据,已经写满

⑥、get(),获取数据

from multiprocessing import Queue
q = Queue(2)
q.put("消息1")
q.put("消息2")
print(q.get()) #消息1
print(q.get()) #消息2

from multiprocessing import Process,Queue
q = Queue(3)
q.put("消息1")
q.put("消息2")
q.put("消息3")
while q.qsize() > 0:
    print(q.get())

⑦、empty(),判断队列中的数据是否空了,True表示空了

from multiprocessing import Queue
q = Queue(2)
q.put("消息1")
q.put("消息2")
print(q.get())   #消息1
print(q.empty()) #False
print(q.get())   #消息2
print(q.empty()) #True

from multiprocessing import Process,Queue
q = Queue(3)
q.put("消息1")
q.put("消息2")
q.put("消息3")
try:
    q.put("消息4",timeout=3,block=False)
except:
    print("消息队列满了")
print(q.get())
print(q.get())
print(q.get())
try:
    print(q.get(timeout=2,block=True))
except Exception as f:
    print(f)
    print("消息队列空了")
print("结束")
"""
消息队列满了
消息1
消息2
消息3

消息队列空了
结束
"""

练习:用多线程实现,两个人生产包子,一个人吃包子

from multiprocessing import Process,Queue
import time
def chef_1(q,name):
    for i in range(1,3):
        a = "第{}个{}包子".format(i,name)
        print("生产:",a)
        q.put(a)
        time.sleep(1)
def chef_2(q,name):
    for i in range(1,3):
        a = "第{}个{}包子".format(i,name)
        print("生产:",a)
        q.put(a)
        time.sleep(1)
def eat(q):
    while True:
        try:
            a = q.get(timeout = 2)
            print("吃:",a)
        except:
            break
def main():
    q = Queue(3)
    p1 = Process(target = chef_1,args = (q,"张三"))
    p2 = Process(target = chef_2,args = (q,"李四"))
    p3 = Process(target = eat,args = (q,))
    p1.start()
    p2.start()
    p3.start()
if __name__ == '__main__':
    main()

6、进程池----使用Pool类创建进程池
①、join()主程序等待所有子进程执行完毕,必须在close()之后
②、close()等待所有进程结束才关闭进程池

from multiprocessing import Process,Queue,Pool
import time
def func(num):
    for i in range(1,11):
        print(num,"进程开始",i)
        print(num,"进程结束",i)
        time.sleep(2)
def main():
    p = Pool(4)
    for i in range(1, 11):
        p.apply_async(func, (i,)) #应用异步
    p.close()
    p.join()
if __name__ == '__main__':
    main()

迅雷下载器

from multiprocessing import Pool
import time
def down_load(movie_name):
    for i in range(5):
        print("电影:{},下载进度:{}%".format(movie_name,i / 4 * 100))
        time.sleep(1)
    return movie_name
def alert(movie_name):
    print("恭喜{}下载完成了...".format(movie_name))
def main():
    movie_lst = ["西红柿首富", "功夫熊猫", "叶问", "功夫", "战狼2", "红海行动"]
    pool = Pool(2)
    for movie_name in movie_lst:
        pool.apply_async(down_load, (movie_name,), callback=alert)
    pool.close()
    pool.join()
if __name__ == '__main__':
    main()

二、线程

1、什么是线程
进程是资源拥有者,创建,撤销与切换存在较大的内存开销,因此需要引入轻量型进程,即线程。

2、进程和线程之间的关系
进程是资源分配的最小单位,线程是CPU调度的最小单位,程序真正执行的时候调用的是线程。每个进程中至少有一个线程。

3、创建线程----需要导入threading线程处理模块

from threading import Thread
import time
count = 0
def sing():
    for i in range(3):
        global count
        count += 1
        print(count, "唱歌")
        time.sleep(1)
def dance():
    for i in range(3):
        global count
        count += 1
        print(count, "跳舞")
        time.sleep(1)
def main():
    t1 = Thread(target=sing)
    t2 = Thread(target=dance)
    t1.start()
    t2.start()
if __name__ == '__main__':
    main()

①、args=(),给函数传递参数

from threading import Thread
import time
def sing(num):
    for i in range(num):
        print(i,"---正在唱歌---")
        time.sleep(1)
def dance(num):
    for i in range(num):
        print(i,"---正在跳舞---")
        time.sleep(1)
def main():
    t1 = Thread(target = sing,args = (3,))
    t2 = Thread(target = dance,args = (3,))
    t1.start()
    t2.start()
if __name__ == '__main__':
    main()

②、join(),当前线程执行完后,其他线程才会继续执行

from threading import Thread
import time
def sing(num):
    for i in range(num):
        print(i,"---正在唱歌---")
        time.sleep(1)
def dance(num):
    for i in range(num):
        print(i,"---正在跳舞---")
        time.sleep(1)
def main():
    t1 = Thread(target = sing,args = (3,))
    t2 = Thread(target = dance,args = (3,))
    t1.start()
    t1.join() #在t2前加载,t1执行完后,t2和主线程才执行
    t2.start()
if __name__ == '__main__':
    main()

③、steDaemon()将当前线程设置成守护线程来守护主程序,当主程序结束后,守护线程就结束,不管是否执行完成。
注意:需要在子线程开启的时候设置守护线程,否则无效。

④、线程对象提供的方法

getName(),获取线程的名称

setName(),设置线程的名称

isAlive(),判断当前线程存活状态

⑤、threading模块提供的方法

currentThread(),返回当前的线程变量。

enumerate(),返回一个包含正在运行的线程的列表。正在运行指的是线程启动后,结束前,不包括启动前和终止后的线程。

activeCount(),返回正在运行的线程数量。与len(threading.enumerate())有相同效果。

4、使用继承方式开启线程
首先定义一个类,继承threading.Thread类
然后重载父类的run()方法。

from threading import Thread
import time
class MyThread(Thread):
    def __init__(self,num):
        super().__init__()
        self.num = num
    def run(self):
        for i in range(self.num):
            print("---run---",i)
            time.sleep(1)

if __name__ == '__main__':
    my_thread = MyThread(3)
    my_thread.start()

5、线程之间共享全局变量

from threading import Thread
g_num = 2
def func1():
    global g_num
    g_num += 3
    print("func1",g_num)
def func2():
    global g_num
    g_num += 5
    print("func2",g_num)
def main():
    t1 = Thread(target=func1)
    t2 = Thread(target=func2)
    t1.start()
    t2.start()
    print("main", g_num)
if __name__ == '__main__':
    main()

6、共享全局变量的问题
多线程开发的时候共享全局变量,会带来资源竞争效果。也就是数据不安全。

from threading import Thread
g_num = 0
def func1(num):
    global g_num
    for i in range(num):
        g_num += 1
    print("func1 =",g_num)
def func2(num):
    global g_num
    for i in range(num):
        g_num += 5
    print("func2 =",g_num)
def main():
    t1 = Thread(target=func1, args=(1000000,))
    t2 = Thread(target=func2, args=(1000000,))
    t1.start()
    t2.start()
    print("main =", g_num)
if __name__ == '__main__':
    main()

练习:

from multiprocessing import Process,Queue
from threading import Thread

def a(q):
    t_aa = Thread(target = aa, args = (q,))
    t_aa.start()
    t_aa.join()

def aa(q):
    q.put([1, 2, 3, ])

def b(q):
    t_bb = Thread(target = bb, args = (q,))
    t_bb.start()
    t_bb.join()

def bb(q):
    print(q.get())

def main():
    q = Queue()
    p_a = Process(target = a,args = (q,))
    p_b = Process(target = b,args = (q,))
    p_a.start()
    p_b.start()

if __name__ == '__main__':
    main()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值