多线程、线程池、GIL锁

一、线程与进程的关系

  默认一个进程至少一个线程

(1)区别:进程只是占内存,线程才消耗CPU;

      线程在进程下行进

      同一进程下不同线程间数据很易共享

二、全局解释器锁(GIL)

GIL是解释器用于同步线程的一种机制,只允许同一时间执行一个线程

常见的GIL解释器有:Cpython与Ruby MRI

三、什么是堵塞线程

  在某一时刻某一个线程在运行一段代码的时候,这时候另一个线程也需要运行,但是在运行过程中的那个线程执行完成之前,另一个线程是无法获取到CPU执行权的(调用sleep方法是进入到睡眠暂停状态,但是CPU执行权并没有交出去,而调用wait方法则是将CPU执行权交给另一个线程),这个时候就会造成线程阻塞。

 

 如果想让主线程等待子线程结束后再运行的话,就需要用到join(),此方法是在start之后

# coding=utf-8
import threading
import time

def chiHuoGuo(people):
    print("%s 吃火锅的小伙伴-羊肉:%s" % (time.ctime(),people))
    time.sleep(1)
    print("%s 吃火锅的小伙伴-鱼丸:%s" % (time.ctime(),people))


class myThread (threading.Thread):   # 继承父类threading.Thread
    def __init__(self, people, name):
        '''重写threading.Thread初始化内容'''
        threading.Thread.__init__(self)
        self.threadName = name
        self.people = people

    def run(self):   # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        '''重写run方法'''
        print("开始线程: " + self.threadName)

        chiHuoGuo(self.people)     # 执行任务
        
        print("结束线程: " + self.name)

print("yoyo请小伙伴开始吃火锅:!!!")

# 创建新线程
thread1 = myThread("xiaoming", "Thread-1")
thread2 = myThread("xiaowang", "Thread-2")

# 开启线程
thread1.start()
thread2.start()

# 阻塞主线程,等子线程结束
thread1.join()
thread2.join()

time.sleep(0.1)
print("退出主线程:吃火锅结束,结账走人")

四、非守护与守护线程

  主线程中,创建了子线程 线程A和线程B,并且在主线程中调用了thread.setDaemon(),这个的意思是,把主线程设置为守护线程,这时候,要是主线程执行结束了,就不管子线程是否完成,一并和主线程退出.

  线程有一个布尔属性叫做daemon。表示线程是否是守护线程,默认取否。当程序中的线程全部是守护线程时,程序才会退出。只要还存在一个非守护线程,程序就不会退出。
主线程是非守护线程。

五、普通锁与递归锁

普通锁

 

 递归锁

 

 

六、实现线程池

import time
import threadpool
def gethtml(url):
    time.sleep(3)
    print(url)

urls = [i for i in range(10)]#生成10个数
pool = threadpool.ThreadPool(10)#建立线程池,开启10个线程
requests = threadpool.makeRequests(gethtml,urls) #提交10个任务到线程池
for req in requests:#开始执行任务
    pool.putRequest(req)#提交

pool.wait() #等待完成

异步线程池:

from concurrent.futures import ThreadPoolExecutor,as_completed
import time
number_list = [1,2,3,4,5,6,7,8,9,10]
#这个模块具有线程池和进程池、管理并行编程任务、处理非确定性的执行流程、进程
#concurrent.futures.Executor 这是一个虚拟集类,提供了异步执行的方法
#submit(fuction,argument) 调度函数(可调用对象)的执行,将qrgument作为参数传入
#map(function,atgument) 将argument作为参数执行函数,以异步的方式
#shutdown(wait=True) 发出让执行者释放所有资源的信号
#concurrent.futures.Future 其中包括函数的异步执行,Future对象是submit任务(即带有参数的functions)到exector的实例
#Executor是抽象类,可以通过子类访问,即线程或进程的Executorpools
#因为,线程或进程的实例时依赖于资源的任务,所以最好以”池“的形式将他们组织在一起,作为可以重用的Launcher或executor
def add_number(data):  #只会消化CPU资源
    item = count(data)
    return item
def count(number):
    for i in range(0,50000):
        i = i + 1
    return i*number

if __name__ == '__main__':
    start_time = time.time()
    #开启线程池
    with ThreadPoolExecutor(max_workers = 5) as t: #max_workers参数为你要开多少个线程

        for item in number_list: #提交任务
            t.submit(add_number,item)

        reqs = [t.submit(add_number,item) for item in number_list]
        for req in as_completed(reqs): #转成可迭代对象
            print(req.result()) #打印信息
    print('程序总耗时:{}'.format(time.time() - start_time))

 

posted @ 2020-11-10 13:49  Eliphaz  阅读(127)  评论(0编辑  收藏  举报