Python 多进程&多线程

多任务

并发:在一段时间内交替执行多个任务

并行:在一段时间内同事一起执行多个任务

进程 Process

进程:一个程序运行在系统之上, 便称这个程序喂一个运行进程,并分配进程ID方便系统管理。操作系统进行资源分配和调度运行的基本单位

单进程 vs 多进程

Python 多进程&多线程_第1张图片

+/ 如果程序向利用计算机的多核优势,让CPU同时处理一些任务,适合用多进程开发

Python 多进程&多线程_第2张图片

 先挖个坑后面学

线程 thread

线程是属于进程的,一个进程可以开启多个线程,执行不同工作,是进程实际工作最小单位

同属一个进程的多个线程共享进程所拥有的全部资源

Python 多进程&多线程_第3张图片

性质

执行顺序

无序,通过CPU调度决定某个线程先执行

结束顺序

主线程会等待所有子线程执行结束后再结束

基本使用

Python 多进程&多线程_第4张图片

创建线程对象

thread_obj = thread.Thread(target=func) 

启动线程执行

thread_obj.start()

import threading
import time

def thread1():
    while True:
        print('thread 1')
        time.sleep(1)

def thread2():
    while True:
        print('thread 2')
        time.sleep(1)

if __name__ == '__main__':
    # create thread
    t1 = threading.Thread(target=thread1)
    t2 = threading.Thread(target=thread2)
    # start thread
    t1.start()
    t2.start()

等待当前线程任务执行完毕后再向下继续执行

thread_obj.join()

执行带有参数的任务

args:以元组方式进行传参 *参数顺序保持一致

kwargs:以字典的方式给任务传参  *字典key和参数名保持一致

守护线程

主线程不等待子线程执行完成,主线程执行完毕后,子线程也自动关闭

me,thod1

threading.Thread(target = work, daemon = True)

method2

线程对象.setDaemon(True)

获取线程信息

current_thread = threading.current_thread()

print(current_thread)

设置/获取名称

name = 线程对象.current_thread().getName()

线程对象.setName()

自定义线程

class Mythread(threading.Thread):

        def run(self):

                print('执行此线程', self.args)


t = Mythread(args = (100, ))
t.start()

线程安全

多个线程操作可能会出现数据混乱的情况

*有些数据类型(如列表)是线程安全的

GIL锁

全局解释器锁(Global Interpreter Lock),让一个进程中同一个时刻只能有一个线程可以被CPU调用

Python 多进程&多线程_第5张图片
 

Lock 同步锁

创建锁

lock_object = threading.RLock()

加锁

线程对象.acquire()

释放锁

线程对象.release() 

e.g

import  threading

lock_object = threading.Lock()

loop = 1000
number = 0

def _add(count):
    lock_object.acquire() #加锁
    global number
    for i in range(count):
        number += 1
        print("t1")
    lock_object.release() #解锁

def _sub(count):
    lock_object.acquire() #申请锁
    global number
    for i in range(count):
        number -= 1
        print("t2")
    lock_object.release() #解锁

t1 = threading.Thread(target=_add,args=(loop,))
t2 = threading.Thread(target=_sub,args=(loop,))
t1.start()
t2.start()

t1.join()
t2.join()

print(number)

RLock 递归锁

Lock不支持锁的嵌套,RLock支持,就是可以加多次锁

Dead Lock 死锁

由于资源竞争或者彼此通信造成阻塞

线程池

线程不是开的越多越好,开的多了可能导致系统性能降低(线程中的上下文切换),因此不建议无限制的创建线程,建议使用线程池

创建

from concurrent.futures import ThreadPoolExecutor
pool = ThreadPoolExecutor(100)   #100个线程的线程池

提交任务

pool.submit(task, sug)

等待线程池执行完毕

pool.shutdown(True)

空闲线程处理额外任务

线程池中提交一个任务,如果有空闲线程,则分配一个线程去执行,执行完毕后再将线程交还给线程池,如果没有空闲线程,则等待

future  =pool.submit(task,url)

future.add_done_callback(done) 

单例模式

import threading
import time

class Singleton:
    instance = None
    lock = threading.RLock()

    def __init__(self,name):
        self.name = name

    def __new__(cls, *args, **kwargs):  #*args,**kwargs 代表任意多个参数
        # 这两行提高效率,可要可不要
        if cls.instance:
            return cls.instance

        with cls.lock:
            if cls.instance:
                return cls.instance
            cls.instance = object.__new__(cls)
            return cls.instance

def task():
    obj = Singleton('x')
    print(obj)

for i in range(10):
    t = threading.Thread(target=task)
    t.start()

线程和进程对比

关系

线程依附在进程里面,没有进程就没有线程

一个进程有一个及以上线程

区别

创建进程的资源开销比创建线程的资源开销大

进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位

线程不能独立执行,必须依存在进程中

优缺点

进程:可多核,开销大

线程:不可多核,开销小

应用:

计算密集型,多进程。 e.g大量的数据计算

IO密集型,多线程 e.g 文件读写,网络数据传输

你可能感兴趣的:(python,网络)