Python--进程、线程

一、进程

(一)什么是进程

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

(二)创建多进程

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)
    t1.start()
    t2.start()

主进程从main()开始执行,执行main函数体,当执行到t1.start()时,创建一个子进程,t1子进程中的代码和主进程相同,只是程序执行的开始是sing函数体。
主进程执行到t2.start()时,同样复制一份主进程代码从danc函数体开始执行

(三)进程的状态

程序有三个状态:就绪,运行和阻塞

(四)进程之间通讯

使用Queue队列,先进先出
两个进程通讯,就是一个子进程往queue中写内容,另一个进程从queue中取出数据
put()方法,向队列中存放数据。如果队列已满,此方法将阻塞直到有空间可用为止。
get(),返回q中的一个项目。如果q为空,此方法将阻塞,直到队列中有数据可用为止。

from multiprocessing import Queue
q = Queue(3) # 3表示容量
q.put('包子') #存放,如果队列已满,阻塞到有空间为止
q.put('香蕉')
q.put('西瓜')
print('执行到这了')
q.get() # 返回一个项目,如果队列已空,阻塞到有项目为止
q.put('猪肘子')
print('开始吃')
print(q.get()) # 先进先出
print(q.get())
print(q.get())
from multiprocessing import Queue
q = Queue(4)
q.put('包子')
q.put('香蕉')
q.put('西瓜')
while q.qsize() > 0: # qsize()队列中项目个数
    print(q.get())

full()如果q已满,返回True
empty()如果调用此方法时q为空,返回True

from multiprocessing import Queue
q = Queue(3)
print(q.empty())
q.put(1)
q.put(2)
q.put(3)
print(q.full())

子进程与父进程

os.getpid():获取自己的进程ID
os.getppid():获取父进程ID

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,))
    p2 = Process(target=dance, args=(99,))
    p1.start()
    p2.start()

生产包子

生产与消费同时进行

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

进程子类化,重新编写run函数

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):# 重新编写run函数,覆盖父类的run方法。进程启动的时候调用此方法
            print('启动进程', i, os.getpid())
            time.sleep(1)
if __name__ == '__main__':
    p = SubProcess(3)
    p.start()
    p1 = SubProcess(3)
    p1.start()

改编:添加生产名,以及确定被谁消费

from multiprocessing import Process, Queue
import time
class ProProcess(Process):
    def __init__(self, q, name):
        super().__init__()
        self.q = q
        self.name = name
    def run(self):
        for i in range(15):
            bz = '包子:%d' % (i + 1)
            print(self.name+'生产' + bz)
            self.q.put(bz)
            time.sleep(1)
class CusProcess(Process):
    def __init__(self, q, name):
        super().__init__()
        self.q = q
        self.name = name
    def run(self):
        for i in range(10):
            bz = self.q.get()
            print(self.name+'消费' + bz)
if __name__ == '__main__':
    q = Queue(30) # 需要传入一个队列
    p = ProProcess(q, 'pp  ')
    p1 = ProProcess(q, 'p11  ')
    p.start()
    p1.start()
    p1.join() # join()主进程要等待该子进程执行完毕后,再执行其他子进程
    print('#####################')
    c = CusProcess(q, 'cc  ')
    c1 = CusProcess(q, 'c11  ')
    c2 = CusProcess(q, 'c22  ')

    c.start()
    c1.start()
    c2.start()

(五)进程池

进程池,达到进程重复利用
创建进程池对象的时候可以指定一个最大进程数,当有新的请求提交到进程池中,如果池中进程数还没有满,那么就会创建一个新的进程用来执行该请求,但是如果池中的进程数满了,该请求就会等待,知道进程池中的进程有结束的了,才会使用这个结束的进程来执行新的任务。
join 主进程等待所有子进程执行完毕,必须在close之后
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(3)
    a = 'abcde'
    for x in a:
        # p.apply(hanshu1, (x,)) # 阻塞,同时只跑一个进程
        p.apply_async(hanshu1, (x,))# 非阻塞,同时进行几个子进程由Pool()里的参数决定
    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)# callback回调
    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 = ['哪吒', '金刚葫芦娃', '黑猫警长', '小猪佩奇']
    p = Pool(3)
    for movie in movies:
        p.apply_async(downLoad, args=(movie,), callback=alert)
    p.close()
    p.join()

二、线程

(一)线程概念

由于进程是资源拥有者,创建、撤销与切换存在较大的内存开销,因此需要引入轻型进程,即线程
进程是资源分配的最小单位,线程是CPU调度的最小单位(程序真正执行的时候调用的是线程),每一个进程中至少有一个线程
进程里的所有线程,共享进程的所有资源

(二)使用threading模块创建线程

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

setDaemon()方法

将当前线程设置成守护线程来守护主线程

传递参数

给函数传递参数,使用线程的关键字args=()进行传递参数

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) # 只能写在start()之前
    # 将当前线程设置成守护线程来守护主线程:
    # 当主线程结束后,守护线程也就结束,不管是否执行完成
    t1.start()
    print('主线程结束了')

join()方法

当前线程执行完后其他线程才会继续执行

treading模块提供的方法

threading.currentThread():返回当前的线程变量
threading.enumerate():返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前。
threading.activeCount() 或 threading.active_count():返回正在运行的线程数量,与len(threading.enumerate())有相同效果

from threading import Thread
import threading
import time
def sing():
    for i in range(10):
        # threading.currentThread()返回当前的线程变量
        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()
    # threading.enumerate()返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的进程
    print(threading.enumerate())
    # 返回正在运行的线程数量,与len(threading.enumerate())有相同效果
    print(threading.activeCount())
    print(threading.active_count())
    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)
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 = T('张三')
    c = C('李四')
    t.start()
    c.start()

(三)共享全局变量的问题

多线程开发时共享全局变量会带来资源竞争效果。数据不安全。(出现脏数据)

import threading
g_num = 0
def hs1():
    global g_num
    for i in range(100000):
        g_num+=1
    print(g_num)
def hs2():
    global g_num
    for i in range(100000):
        g_num += 1
    print(g_num)
if __name__ == '__main__':
    t1 = threading.Thread(target=hs1)
    t2 = threading.Thread(target=hs2)
    t1.start()
    t2.start()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
探索全栈前端技术的魅力:HTML+CSS+JS+JQ+Bootstrap网站源码深度解析 在这个数字化时代,构建一个既美观又功能强大的网站成为了许多开发者和企业追逐的目标。本份资源精心汇集了一套完整网站源码,融合了HTML的骨架搭建、CSS的视觉美化、JavaScript的交互逻辑、jQuery的高效操作以及Bootstrap的响应式设计,全方位揭秘了现代网页开发的精髓。 HTML,作为网页的基础,它构建了信息的框架;CSS则赋予网页生动的外观,让设计创意跃然屏上;JavaScript的加入,使网站拥有了灵动的交互体验;jQuery,作为JavaScript的强力辅助,简化了DOM操作与事件处理,让编码更为高效;而Bootstrap的融入,则确保了网站在不同设备上的完美呈现,响应式设计让访问无界限。 通过这份源码,你将: 学习如何高效组织HTML结构,提升页面加载速度与SEO友好度; 掌握CSS高级技巧,如Flexbox与Grid布局,打造适应各种屏幕的视觉盛宴; 理解JavaScript核心概念,动手实现动画、表单验证等动态效果; 利用jQuery插件快速增强用户体验,实现滑动效果、Ajax请求等; 深入Bootstrap框架,掌握移动优先的开发策略,响应式设计信手拈来。 无论是前端开发新手渴望系统学习,还是资深开发者寻求灵感与实用技巧,这份资源都是不可多得的宝藏。立即深入了解,开启你的全栈前端探索之旅,让每一个网页都成为技术与艺术的完美融合!
探索全栈前端技术的魅力:HTML+CSS+JS+JQ+Bootstrap网站源码深度解析 在这个数字化时代,构建一个既美观又功能强大的网站成为了许多开发者和企业追逐的目标。本份资源精心汇集了一套完整网站源码,融合了HTML的骨架搭建、CSS的视觉美化、JavaScript的交互逻辑、jQuery的高效操作以及Bootstrap的响应式设计,全方位揭秘了现代网页开发的精髓。 HTML,作为网页的基础,它构建了信息的框架;CSS则赋予网页生动的外观,让设计创意跃然屏上;JavaScript的加入,使网站拥有了灵动的交互体验;jQuery,作为JavaScript的强力辅助,简化了DOM操作与事件处理,让编码更为高效;而Bootstrap的融入,则确保了网站在不同设备上的完美呈现,响应式设计让访问无界限。 通过这份源码,你将: 学习如何高效组织HTML结构,提升页面加载速度与SEO友好度; 掌握CSS高级技巧,如Flexbox与Grid布局,打造适应各种屏幕的视觉盛宴; 理解JavaScript核心概念,动手实现动画、表单验证等动态效果; 利用jQuery插件快速增强用户体验,实现滑动效果、Ajax请求等; 深入Bootstrap框架,掌握移动优先的开发策略,响应式设计信手拈来。 无论是前端开发新手渴望系统学习,还是资深开发者寻求灵感与实用技巧,这份资源都是不可多得的宝藏。立即深入了解,开启你的全栈前端探索之旅,让每一个网页都成为技术与艺术的完美融合!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值