zoukankan      html  css  js  c++  java
  • python基础--线程、进程

    并发编程:
        操作系统:(基于单核研究)

        多道技术:

            1、空间上的复用

                多个程序共用一个计算机

            2、时间上的复用

                切换+保存状态

                例如:洗衣 烧水 做饭

                切换:

                    1、程序遇到IO操作系统会立刻剥夺着CPU的执行权限   IO:input、sleep、accept、recv...阻塞  日常生活中使用的软件通常都是IO密集型

                    2、当你的程序长时间占用CPU的时候也会被操作系统剥夺CPU的执行权限

        进程理论:

            进程调度:

                时间片轮转法+多级反馈队列

            进程三状态:运行、就绪、阻塞

                ps:程序不会立刻进入运行状态,都会先在就绪态等待CPU的执行

            同步异步:指的是任务的提交方式

                同步:提交任务之后原地等待任务的返回结果  期间不做任何事

                异步:提交任务之后就立刻执行下一行代码  不等待任务的返回结果 >>> 结果的获取使用异步回调机制

            阻塞非阻塞:指的是程序的运行状态

                阻塞:阻塞态

                非阻塞:就绪态或者运行态

        创建进程的两种方式:

            使用Process实例化

            继承Process类重写run方法

            ps:windows在开启进程的时候必须在__main__代码块内,因为windows是以模块导入的方式从上执行代码

        什么是进程:正在运行的程序

            一个进程对应到内存中就是一块独立的内存空间

        join方法:主进程等待某个指定的子进程运行结束,不影响其他子进程的运行

        进程对象及其它方法:

            current_process().pid

            os.getpid

            os.getppid

            terminate()

            is_alive()

        守护进程:

            daemon:这一句必须放在start之前使用

        进程数据是隔离的

        互斥锁:

            多个进程操作一份数据的时候会出现数据错乱的现象

            避免?:将操作数据的部分加锁处理(会将并发变成串行牺牲了效率但是保证了数据的安全)

            强锁:acpuire()

            释放锁:release()

            

    进程间的通信:

    from multiprocessing import Queue
    q = Queue(5)  # 括号内可以传参数 表示的是这个队列的最大存储数
    # 往队列中添加数据
    q.put(1)
    q.put(2)
    # print(q.full())  # 判断队列是否满了
    q.put(3)
    q.put(4)
    q.put(5)
    q.put(6)  # 当队列满了之后 再放入数据 不会报错 会原地等待 直到队列中有数据被取走(阻塞态)
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.empty())  # 判断队列中的数据是否取完
    print(q.get())
    print(q.get())
    print(q.empty())
    print(q.get_nowait())  # 取值 没有值不等待直接报错
    print(q.get())  # 当队列中的数据被取完之后 再次获取 程序会阻塞 直到有人往队列中放入值
    """
    full
    get_nowait
    empty
    都不适用于多进程的情况
    """

    进程间通信IPC机制:

    from multiprocessing import Process,Queue
    
    def producer(q):
        q.put('hello GF~')
    
    def consumer(q):
        print(q.get())
    
    if __name__ == '__main__':
        q = Queue()
        p = Process(target=producer,args=(q,))
        c = Process(target=consumer, args=(q,))
        p.start()
        c.start()
    
    
    """
    子进程放数据 主进程获取数据
    两个子进程相互放 取数据
    """

    生产者消费者模型:

    from multiprocessing import Process,Queue,JoinableQueue
    import random
    import time
    
    
    def producer(name,food,q):
        for i in range(10):
            data = '%s生产了%s%s'%(name,food,i)
            time.sleep(random.random())
            q.put(data)
            print(data)
    
    def consumer(name,q):
        while True:
            data = q.get()
            if data == None:break
            print('%s吃了%s'%(name,data))
            time.sleep(random.random())
            q.task_done()  # 告诉队列你已经从队列中取出了一个数据 并且处理完毕了
    
    
    
    if __name__ == '__main__':
        q = JoinableQueue()
    
        p = Process(target=producer,args=('大厨','馒头',q))
        p1 = Process(target=producer,args=('跟班','生蚝',q))
        c = Process(target=consumer,args=('william',q))
        c1 = Process(target=consumer,args=('john',q))
        p.start()
        p1.start()
        c.daemon = True
        c1.daemon = True
        c.start()
        c1.start()
        p.join()
        p1.join()
    
        q.join()  # 等到队列中数据全部取出

    线程:

        进程和线程都是虚拟单位,都是用来帮助我们形象的描述某种事物

        进程:资源单位

        线程:执行单位

            将内存比成加工厂,那么进程就是相当于工厂里面的车间,那么线程就是车间里面的流水线

            ps:每个进程都自带一个线程,线程才是真正的执行单位,进程只是在线程运行过程中提供代码运行所需要的资源

        为什么要有线程:

            开进程:

                1、申请内存空间  耗资源

                2、“拷贝代码”  耗资源

            开线程:

                一个进程内可以开多个线程,并且线程与线程之间数据是共享的

                ps:开启线程的开销要远远小于启动进程的开销

        开启线程的两种方式:

    from threading import Thread
    import time
    
    def task(name):
        print('%s is running'%name)
        time.sleep(3)
        print('%s is over'%name)
    # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内
    t = Thread(target=task,args=('william',))
    t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
    # 小的代码执行完 线程就已经开启了
    print('')
    from threading import Thread
    import time
    
    class MyThread(Thread):
        def __init__(self,name):
            super().__init__()
            self.name = name
    
        def run(self):
            print('%s is running'%self.name)
            time.sleep(3)
            print('%s is over'%self.name)
    
    t = MyThread('john')
    t.start()
    print('')

        线程对象方法:开启线程不需要在__main__代码块内,但是习惯性的还是写在__main__代码块内

    from threading import Thread, current_thread, active_count
    import time
    import os
    
    def task(name, i):
        print('%s is running'%name)
        # print('子current_thread:',current_thread().name)
        # print('子', os.getpid())
        time.sleep(i)
    
        print('%s is over'%name)
    # 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内
    t = Thread(target=task, args=('john',1))
    t1 = Thread(target=task, args=('william',2))
    t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
    t1.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
    t1.join()  # 主线程等待子线程运行完毕
    print('当前正在活跃的线程数',active_count())
    # 小的代码执行完 线程就已经开启了
    print('')
    # print('主current_thread:',current_thread().name)
    # print('主', os.getpid())

        守护线程:主线程的结束也就意味着进程的结束,主线程必须等待其它非守护线程的结束才能结束(意味着子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了)

    from threading import Thread,current_thread
    import time
    
    
    def task(i):
        print(current_thread().name)
        time.sleep(i)
        print('GG')
    # for i in range(3):
    #     t = Thread(target=task,args=(i,))
    #     t.start()
    t = Thread(target=task,args=(1,))
    t.daemon = True
    t.start()
    print('')

        线程间相互通信:

    from threading import Thread
    
    
    money = 666
    
    def task():
        global money
        money = 999
    
    t = Thread(target=task)
    t.start()
    t.join()
    print(money)  # money变成了999

        线程中的互斥锁:

            

    from threading import Thread,Lock
    import time
    
    
    n = 100
    
    def task(mutex):
        global  n
        mutex.acquire()
        tmp = n
        time.sleep(0.1)
        n = tmp - 1
        mutex.release()
    
    t_list = []
    mutex = Lock()
    for i in range(100):
        t = Thread(target=task,args=(mutex,))
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()
    print(n)

            

        线程中的小例子:

            

    from threading import Thread
    from multiprocessing import Process
    import time
    def foo():
        print(123)
        time.sleep(1)
        print("end123")
    
    def bar():
        print(456)
        time.sleep(3)
        print("end456")
    
    if __name__ == '__main__':
        t1=Thread(target=foo)
        t2=Thread(target=bar)
        t1.daemon=True
        t1.start()
        t2.start()
        print("main-------")

        这里需要注意的是:主线程要等待非守护线程的结束才会结束所以在这里面end123也是会输出的

  • 相关阅读:
    封装和参数调用(格式修改)
    今天休息
    2018.1.9内部类
    2018.1.8转型
    环境变量
    环境变量
    计算机的高级语言
    常用的设计模式
    常用的设计模式
    【python3】中 elif 的使用
  • 原文地址:https://www.cnblogs.com/tulintao/p/11340483.html
Copyright © 2011-2022 走看看