多任务:进程和线程

一、多任务

定义: 多任务就是同一时刻多个任务同时执行。

实现多任务的原理: CPU在多个应用程序之间的高速切换。

二、进程

定义: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

程序和进程

  • 程序: 编写完毕的代码,在没有运行的时候,称之为程序。
  • ** 进程:** 正在运行着的代码,就成为进程。
  • 对应关系: 程序只有一个,进程可以有多个

进程的创建:
新创建的进程在内存独立开辟一块空间,不与其他进程共享空间、数据。
同一个进程中,新创建的线程与此进程里其他线程共享空间、数据。

多进程
实例:一定要把开进程的代码写在if name==‘main’:下面

from multiprocessing import Process
import time
def sing():
    for i in range(10):
        print("我在唱第{}句歌词".format(i+1))
        time.sleep(1)
def dance():
    for i in range(10):
        print("我在跳第{}段舞蹈".format(i+1))
        time.sleep(1)
if __name__=="__main__":  # 写多线程,进程必须要写的
    t1=Process(target=sing)
    t2=Process(target=dance)  # target表示调用对象,即子进程要执行的任务
    t1.start()
    t2.start()

多进程同时进行

from multiprocessing import Process
count=0
def hanshu1():
    global count
    for i in range(1000):
        count+=1
    print("函数1:",count)
def hanshu2():
    global count
    for i in range(1000):
        count+=1
    print("函数2:",count)
if __name__=="__main__":  # 写多线程,进程必须要写的
    t1=Process(target=hanshu1)
    t2=Process(target=hanshu2)
    t1.start()
    t2.start()

注意:

  1. 需要使用关键字的方式来指定参数
  2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号

进程里的一些方法:

  1. p.start():启动进程,并调用该子进程中的p.run()

  2. p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法

  3. p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,
    需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程

  4. getppid()父进程id

  5. getpid() #当前进程id

进程的状态:
就绪:分配到除CPU以外的所有必要资源,只要获得处理机便可以立即执行
阻塞:状态正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态
执行:状态当进程已获得处理机,其程序正在处理机上执行

队列 (先进先出的存储数据结构)
实现进程之间的通讯
两个进程通讯:就是一个子进程往queue中写内容,另一个进程从queue中取出数据
队列实例:

from multiprocessing import Queue

q=Queue(4)
q.put("包子")
q.put("香蕉")
q.put("西瓜")
print("执行到这了")
q.put("猪肘子")
print("开始吃")
print(q.get())  # 先进先出
print(q.get())
print(q.get())
print(q.get())

from multiprocessing import Queue

q=Queue(4)
q.put("包子")
q.put("香蕉")
q.put("西瓜")
print(q.qsize())

while q.qsize()>0:  # 与上面代码功能相同
    print(q.get())

队列满和空时阻塞

from multiprocessing import Queue

q=Queue(3)
q.put(10)
q.put(20)
q.put(30)
try:
    q.put(40,block=False)  # block堵塞,block=False,不想等直接结束,报异常
except:
    print("队满了,没法再装了")
print("到这了")

from multiprocessing import Queue

q=Queue(3)
q.put(10)
q.put(20)
print(q.get())
print(q.get())
try:
    print(q.get(block=False))
except:
    print("没人放东西了")
print("程序走到这了")
# 10
# 20
# 没人放东西了
# 程序走到这了

两个进程间存一个和取一个的例子:

from multiprocessing import Queue,Process
import time

def produce(q):
    for i in range(10):
        bz="包子:%d"%(i+1)
        print("生产"+bz)
        q.put(bz)
        time.sleep(1)

def consumer(q):
    for i in range(10):
        bz=q.get()
        print("消费"+bz)
if __name__=='__main__':
    q=Queue(1)
    p1=Process(target=produce,args=(q,))
    p2=Process(target=consumer,args=(q,))
    p1.start()
    p2.start()
# in __init__
#     self._args = tuple(args)

进程的子类化

from multiprocessing import Process
import os,time

class SubProcess(Process):
    def __init__(self,x):
        super().__init__()
        self.x=x
    def run(self):  # 重新编写run函数,覆盖父类的run方法。进程启动的时候调用此方法
        for i in range(self.x):
            print("启动进程",i,os.getpid())
            time.sleep(1)

if __name__=="__main__":
    p=SubProcess(3)
    p.start()
    p1 = SubProcess(3)
    p1.start()
# 启动进程 0 8340
# 启动进程 0 6872
# 启动进程 1 8340
# 启动进程 1 6872
# 启动进程 2 8340
# 启动进程 2 6872

用子类化实现生产和消费包子

from multiprocessing import Process,Queue
import time

class Producer(Process):
    def __init__(self, q):
        super().__init__()
        self.q=q
    def run(self):
        for i in range(10):
            bz="包子:%d"%(i+1)
            print("生产"+bz)
            self.q.put(bz)
            time.sleep(1)

class Consumer(Process):
    def __init__(self, q):
        super().__init__()
        self.q=q
    def run(self):  # 必须写run
        for i in range(10):
            bz=self.q.get()
            print("消费"+bz)
if __name__=='__main__':
    q = Queue(1)
    p1=Producer(q)
    p2=Consumer(q)
    p1.start()
    p2.start()

进程池Pool
作用: 达到进程重复利用
join 主进程等待所有子进程执行完毕,必须在close之后
close 等待所有进程结束才关闭线程池

from multiprocessing import Pool
import Pool
import time

def hanshu1(name):
    for i in range(5):
        print(name,i)
        time.sleep(1)

if __name__ == '__main__':
    p=Pool(5)
    a="abcde"
    for x in a:
        p.apply(hanshu1,(x,))  # 阻塞,同时只跑一个进程
    p.close()


from multiprocessing import Pool
import time

def hanshu1(name):
    for i in range(5):
        print(name,i)
        time.sleep(1)

if __name__ == '__main__':
    p=Pool(5)
    a = "abcde"
    for x in a:
        p.apply_async(hanshu1,(x,))  # 不阻塞,同时可以跑多个进程
    p.close()
    p.join()  # 阻塞主进程,等待子进程结束

练习进程池

from multiprocessing import Pool
import time

def zuoye(name):
    print(name,"我在写代码")
    time.sleep(1)
    return name+"写完代码了"
def chouyan(status):
    print("去抽烟因为"+status)

if __name__ == '__main__':
    p=Pool(1)
    p.apply_async(zuoye,("张三",),callback=chouyan)  # 先走作业,敲完代码再走抽烟
    p.close()
    p.join()

# 张三 我在写代码
# 去抽烟因为张三写完代码了

下载器工作原理

from multiprocessing import Pool
import time

def downLoad(movie):
    for i in range(5):
        print(movie,"下载进度%.2f%%"%((i+1)/5*100))
        time.sleep(1)
    return movie
def alert(name):
    print(name,"下载完毕,请收看")

if __name__ == '__main__':
    movies=['哪吒','金刚葫芦娃','黑猫警长','小青龙','亚洲飞鹰','A计划']
    p=Pool(3)
    for movie in movies:
        p.apply_async(downLoad,args=(movie,),callback=alert)
    p.close()
    p.join()

线程

import time
from threading import Thread
count=0

def hanshu1():
    global count
    for i in range(10):
        count+=1
    print("函数1",count)
def hanshu2():
    global count
    for i in range(10):
        count+=1
    print("函数2",count)  # 线程共用进程里的所有资源,t1,执行完结果为10,因为共用资源,所有函数2 count为20

if __name__ == '__main__':
    t1=Thread(target=hanshu1)
    t2=Thread(target=hanshu2)
    t1.start()
    t1.join()
    t2.start()
    t2.join()
# 函数1 10
# 函数2 20

多线程

import time
from threading import Thread

def sing():
    for i in range(10):
        print("唱歌%d"%(i+1))
        time.sleep(1)
def dance():
    for i in range(10):
        print("跳舞%d"%(i+1))
        time.sleep(1)
if __name__ == '__main__':  # 在一个进程里,线程
    t1=Thread(target=sing)
    t2=Thread(target=dance)
    t1.start()
    t2.start()

线程的传参

import time
from threading import Thread

def get(num):
    for i in range(num):
        print(i)
        time.sleep(1)
if __name__ == '__main__':
    t1=Thread(target=get,args=(5,))
    t1.setDaemon(True)
    t1.start()
    print("主线程结束了")
# 0
# 主线程结束了
# 1
# 2
# 3
# 4

join()方法

import time
from threading import Thread
def sing():
    for i in range(10):
        print("唱歌%d"%(i+1))
        time.sleep(1)
def dance():
    for i in range(10):
        print("跳舞%d"%(i+1))
        time.sleep(1.5)
if __name__ == '__main__':  # 在一个进程里,线程
    t1=Thread(target=sing)
    t2=Thread(target=dance)
    t1.start()
    # t1.join()
    t2.start()
    t1.join()
    t2.join()
    print("结束")

线程的方法

import time,threading
from threading import Thread
def sing():
    for i in range(10):
        print("唱歌%d"%(i+1),threading.current_thread())
        time.sleep(1)
def dance():
    for i in range(10):
        print("跳舞%d"%(i+1),threading.current_thread())
        time.sleep(1.5)
if __name__ == '__main__':  # 在一个进程里,线程
    t1=Thread(target=sing,name="刘德华")
    t2=Thread(target=dance,name="张惠妹")
    t1.start()
    # t1.join()
    t2.start()
    print(threading.enumerate())  # 跳舞1[<_MainThread(MainThread, started 1544)>, <Thread(刘德华, started 4608)>, <Thread(张惠妹, started 9900)>]
    print(threading.active_count(),len(threading.enumerate()))

    t1.join()
    t2.join()
    print("结束")

线程子类化

import time,threading
from threading import Thread

class T(Thread):
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):
        for i in range(10):
            print(self.name,"跳舞%d"%(i+1))
            time.sleep(1)
class C(Thread):
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):
        for i in range(10):
            print(self.name,"唱歌%d"%(i+1))
            time.sleep(1)
if __name__ == '__main__':
    t="张三"
    t1=T(t)
    # t1 = T("张三")
    t2=C(t)
    t1.start()
    t2.start()

共享全局变量

import threading

g_num=0
def hanshu1():
    global g_num
    g_num+=5
def hanshu2():
    print(g_num)  # 5
if __name__ == '__main__':
    t1=threading.Thread(target=hanshu1)
    t2=threading.Thread(target=hanshu2)
    t1.start()
    t2.start()

会达不到预期效果

import threading

g_num=0
def hs1():
    global g_num
    for i in range(100000):
        g_num+=1
    print("函数1",g_num)
def hs2():
    global g_num
    for i in range(100000):
        g_num += 1
    print("函数2",g_num)
if __name__ == '__main__':
    t1=threading.Thread(target=hs1)
    t2=threading.Thread(target=hs2)
    t1.start()  # 会达不到预期效果
    t2.start()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值