线程与进程的却别:
进程在执行过程之中拥有独立的内存单元,而多个线程共享内存,从而极大的提升了程序的运行效率。
多线程共享全局变量,线程是进程的执行单元,进程时系统分配资源的最小执行单位,所以在同一个进程中的多线程是共享资源的
多线程基本的实现方式:
t1 = threading.Thread(target=fun,args=('t1',)) target为执行的函数名,args为传入的参数
t2 = threading.Thread(target=run,args=('t2',))
t1.start()
t2.start()
上述就是一个基本的多线程实现方法,下面讲述一些常用的方法:
守护线程t1.setDarmon('True'):
设置守护线程之后当主线程结束后子线程会立即结束,如果想要主线程等待子线程结束之后再结束,需要使用t1.join()方法
线程同步机制:
例如当我们在实现一个存钱取钱的逻辑时,存钱线程可分为money,money+1,money=money+1三个步骤,取钱线程同理,在这一过程中如果不使用锁机制,较少次数内可能不会会发生错误,当次数较多时就会发生错误了。
互斥锁/同步锁(lock):
首先需要实例化一个锁对象:lock = threading.Lock();接着在操作变量之前加锁:lock.acquire();最后在操作变量之后解锁:lock.release();
递归锁(Rlock):
RLcok类的用法和Lock类一模一样,但它支持嵌套,在多个锁没有释放的时候一般会使用RLock类,在同一线程内,对RLock进行多次acquire()操作,程序不会阻塞。(感觉有点类似php中的require和require_once哈哈哈)
线程池:
基本原理:把任务放进队列中去,然后开N个线程,每个线程都去队列中取一个任务,执行完了之后告诉系统说我执行完了,然后接着去队列中取下一个任务,直至队列中所有任务取空,退出线程。 由于线程预先被创建并放入线程池中,同时处理完当前任务之后并不销毁而是被安排处理下一个任务,因此能够避免多次创建线程,从而节省线程创建和销毁的开销,能带来更好的性能和系统稳定性。
线程数计算公式:
N核服务器,通过执行业务的单线程分析出本地计算时间为x,等待时间为y,则工作线程数(线程池线程数)设置为 N*(x+y)/x,能让CPU的利用率最大化。由于有GIL的影响,python只能使用到1个核。
使用线程池流程:
1、调用 ThreadPoolExecutor 类的构造器创建一个线程池;2、定义一个普通函数作为线程任务;3、调用 ThreadPoolExecutor 对象的 submit() 方法来提交线程任务;4、当不想提交任何任务时,调用 ThreadPoolExecutor 对象的 shutdown() 方法来关闭线程池。