Python中的进程和线程(20)


多任务:对于电脑来说多任务就是同时运行多个应用程序。
在python中实现多进程有三种方式,进程、线程、协程。

进程

进程:运行起来的应用程序就称之为进程。
程序和进程的对应关系:程序只有一个,但是进程可以有多个。
进程是系统进行资源分配和调度的基本单位。

创建多进程

#使用进程让唱歌和跳舞一起执行
import time
from multiprocessing import Process
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)
    t1.start()#用来启动进程并执行任务
    t2.start()
    #不使用多进程实现先唱后跳
    # sing()
    # dance()

进程和全局变量

from multiprocessing import Process
# count=0
# def hanshu1():
#     for i in range(1000):
#         count+=1
#         #count=count+1 #局部变量和全局变量冲突
#每个进程访问变量互补影响
count=0
def hanshu1():
    global count
    for i in range(1000):
        count=count+1
    print('函数1:',count)
def hanshu2():
    global count
    for i in range(1000):
        count=count+1
    print('函数2:',count)
if __name__=="__main__":
    t1=Process(target=hanshu1)
    t2=Process(target=hanshu2)
    t1.start()#1000
    t2.start()#1000
    # hanshu1()#1000
    # hanshu2()#2000

传递参数和进程号

from multiprocessing import Process
import os
def sing(num):
    print("参数是",num,'进程的ID',os.getpid(),'父进程',os.getppid())
def dance(num):
    print("参数是",num,'进程的ID',os.getpid(),'父进程',os.getppid())
if __name__=='__main__':
    print('主进程ID',os.getpid())
    p1=Process(target=sing,args=(9,))# self._args = tuple(args)
    p2=Process(target=dance,args=(99,))
    p1.start()
    p2.start()
'''
主进程ID 5024
参数是 99 进程的ID 12236 父进程 5024
参数是 9 进程的ID 12244 父进程 5024
'''

进程的状态

就绪状态,就绪、执行状态,阻塞状态

进程之间通信

可以使用队列,队列:先进先出的存储结构。
两个进程通讯,就是一个子进程往队列中写,另一个取。

from multiprocessing import Queue
q=Queue(4)#表示只能存放4个数据,队列对象返回值q是
q.put('包子')
q.put('香蕉')
q.put('西瓜')
print('执行到这了')
q.put('馒头')
print('开始吃')
#队列中有多少数据
print(q.qsize())
#判断队列中是否放满了
print(q.full())
while q.qsize()>0:
    print(q.get())#获取数据
print(q.empty())#判断队列是否为空
'''
执行到这了
开始吃
4
True
包子
香蕉
西瓜
馒头
True

'''

put() get()方法

from multiprocessing import Queue
q=Queue(3)#表示只能存放3个数据,队列对象返回值q是
q.put(10)
q.put(20)
q.put(30)
#1
try:
    q.put(40,block=False)#阻塞
except:
    print("队满了,没法再装了")
print('到这了')
#2
from multiprocessing import Queue
q=Queue(3)#表示只能存放3个数据,队列对象返回值q是
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 producer(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(3)
    p1 = Process(target=producer, args=(q,))
    p2 = Process(target=consumer, args=(q,))
    p1.start()
    p2.start()

进程子类化

#进程子类化
from multiprocessing import Process
import  os,time
class SubProcess(Process):#进程子类化
    def __init__(self,x):
        super().__init__()
        self.x=x
    def run(self):
        for i in range(self.x):
            print("启动进程",os.getpid())
            time.sleep(1)
if __name__=='__main__':
    p=SubProcess(3)#
    p.start()
    p1=SubProcess(3)
    p1.start()

生产者和消费者子类化

from multiprocessing import Queue,Process
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):
        for i in range(10):
            bz=self.q.get()
            print('吃',bz)
if __name__=='__main__':
    q=Queue(5)
    p1=Producer(q)
    p2=Consumer(q)
    p1.start()
    p2.start()

进程池

#进程池:p.apply(hanshu1,(x,))#阻塞,同时跑一个进程
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='abcdefghijk'
    for x in a:
        p.apply(hanshu1,(x,))#阻塞,同时跑一个进程
    p.close()#阻塞主进程,等待子进程结束
'''
a 0
a 1
a 2
a 3
a 4
b 0
b 1
b 2
b 3
b 4
c 0
'''
#进程池:apply_async是异步非阻塞式的。
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='abcdefghijk'
    for x in a:
        p.apply_async(hanshu1,(x,))#apply_async是异步非阻塞式的。
    p.close()#阻塞主进程,等待子进程结束
    p.join()

"""
a 0
b 0
c 0
d 0
e 0
a 1
b 1
c 1
d 1
e 1
a 2
b 2
c 2
d 2
e 2
a 3
b 3
c 3
"""
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()#join 主进程等待所有子进程执行完毕,必须在close之后

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

例子:迅雷下载器

#例子:迅雷下载器
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()

线程

进程是资源分配的最小单位,线程是CPU调度的最小单位(程序真正调用的是线程),每一个进程至少有一个线程。

#他两是是一个进程
from  threading import Thread
import time
import os
def sing():
    for i in range(10):
        print("唱儿歌%d"%(i+1),os.getpid())
        time.sleep(1)
def dance():
    for i in range(10):
        print("跳舞%d"%(i+1),os.getpid())
        time.sleep(1)
if __name__ == '__main__':
    t1=Thread(target=sing)
    t2=Thread(target=dance)
    t1.start()
    t2.start()

守护线程

from threading import Thread
import time
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('主线程结束了')

join()

from  threading import Thread
import time
import os
def sing():
    for i in range(10):
        print("唱儿歌%d"%(i+1),os.getpid())
        time.sleep(1)
def dance():
    for i in range(10):
        print("跳舞%d"%(i+1),os.getpid())
        time.sleep(1)
if __name__ == '__main__':
    t1=Thread(target=sing)
    t2=Thread(target=dance)
    t1.start()
    # t1.join()#在t2前加载,t1执行完后,t2和主线程才执行这里join会阻塞t2,在执行跳舞的时候,主线程先结束
    t2.start()
    # t1.join()#t1,t2,执行完成后主线程才执行,在这里会阻塞主进程,最后执行结束
    t1.join()
    t2.join()
    print('结束')

threading.current_thread():返回当前的线程变量
threading.enumerate():返回一个正在运行线程的list
threading.active_count():代表enumerate()里存活的线程数量

#他两是是一个进程
from  threading import Thread
import threading
import time
import os
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)
if __name__ == '__main__':
    t1=Thread(target=sing,name="刘德华")#给线程起了个名字
    t2=Thread(target=dance,name='张惠妹')
    t1.start()
    t2.start()

    print(threading.enumerate())#返回一个正在运行线程的list
    print(threading.active_count(),len(threading.enumerate()))#代表enumerate()里存活的线程数量
    t1.join()
    t2.join()
    print('结束')

线程子类化

#线程子类化
import  threading,time
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)
if __name__ == '__main__':
    t=T("张三")
    t.start()
#线程子类化
import  threading,time
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 T1(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=T("张三")
    t.start()
    y=T1("zhang")
    y.start()

共享全局变量的问题

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

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

from threading import Thread
g_num=0
def hanshu1():
    global g_num
    for i in range(100000):
        # time.sleep(1)
        g_num+=1
    print("函数1",g_num)
def hanshu2():
    global  g_num
    for i in range(100000):
        # time.sleep(1)
        g_num+=1
    print("函数2",g_num)
if __name__ == '__main__':
    t1=Thread(target=hanshu1)
    t2=Thread(target=hanshu2)
    t1.start()
    # t1.join()
    t2.start()
'''
函数1 143776
函数2 192931

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值