6.线程

线程的概念:

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程实际的运作单位之一
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条进程并行不同的任务

创建线程

以函数形式创建多线程的方法

import threading    导入模块
t1=threading.Thread(target=函数名,args=(给函数的参数))#创建一个多进程对象
t1.start()                 启动新建的进程对象,即开启新进程
t1.join() 该线程执行完毕后,才能执行该代码,在子程序完成运行前,这个子线程的父线程将一直被阻塞
threading.current_thread() 返回当前的线程名,在主线程就返回主线程,在子线程中就返回子线程+编号
threading.current_count() 返回当前存活的进程数
t1.setdaemon(True) 守护线程,一旦给某个子线程设置守护线程,只要主线程结束,就立即结束该子线程,没有设置守护进程的函数,依然继续执行

举例如下:

def a():
    print('函数a执行')
    time.sleep(5)
    print('a函数结束')
t1=threading.Thread(target=a)

if __name__=="__main__":
    t1.setDaemon(True)  #设置守护线程,注意一定要设置在start前
    t1.start()
    print("主线程结束")

如上代码,只要主线程一结束,子线程也立即结束,线程守护使正在阻塞的子程序立即结束

类继承方式创建多线程

新建一个类,继承threading.Thread,
如果有参数,就重写该类的__init__方法
定义每个线程要运行的函数,函数名一定为run,因为这是父类要执行的方法
实例化对象
对象.start 即可启动新建的多线程

举例如下:

import threading
import time
class Hello(threading.Thread):
    def __init__(self,a):
        threading.Thread.__init__(self)   #该代码固定,不可改变
        self.a=a
    def run(self):      #run方法没有执行,但是在新建的线程中依然执行了,这是因为父类方法一定调用执行了该run方法
        print('线程开始%s'%self.a)
        time.sleep(3)
        print('线程结束%s'%self.a)
if __name__=='__main__':
    print('主线程开始')
    hello=Hello(2)
    hello.start()
    time.sleep(2)
    print('主线程结束')

多线程时系统的运行方式:

IO密集型任务或函数:在程序中存在阻塞的情况   

计算密集型任务函数:在程序运行时没有阻塞情况的代码

在Python中,多线程是cpu在运行是来回替换线程运行的,如果是IO密集型任务函数,cpu会在一个线程阻塞时执行另一个线程,使用多线程会节省程序的运行时间,如果是计算密集型函数,多线程就无法减少程序运行的总时间。反而会因为cpu的来回切换,增加cpu处理程序的时间,反而不如单线程执行.

结论:
在python里,如果任务是IO密集型的,可以用多线程;如果是计算密集型,使用多线程没有帮助,无法减少代码执行时间

GIL

python的多线程中,即使电脑是多核,也只能调用一个cpu来执行多线程程序,这是因为python中的GIL

GIL:全局解释器锁,被加在解释器上,是cpython解释器中的独有问题

GIL的作用:在同一时刻,只能由一个线程进入解释器,所以多个线程只能来回切换进入解释器运行,解释器再调用cpu,因此python中实际上是没有多进程的

想让一端函数使用一个cpu,在python中,就只能使用多进程

 

在普通代码中,全程只有一个线程,代码从上到下依次进行
在多线程代码中,启动几个线程,程序就在原有的进程上添加几个线程,几个线程之间同时运行,线程之间可以互相影响,相互通信的.

如下是一个函数创建多线程的代码:

import threading
import time
def foo(c):
    start = time.time()
    time.sleep(3)
    print('foo%s结束' % c)
    end = time.time()
    print(end - start)
def bar(c):
    start = time.time()
    time.sleep(5)    #sleep时代码不运该进程行任何程序
    print('bar%s结束' % c)
    end = time.time()
    print(end - start)

if __name__=='__main__':
    t1=threading.Thread(target=foo,args=(1,))  #为函数foo()创建一个线程对象
    t2=threading.Thread(target=bar,args=(2,)) #为函数bar()创建一个线程对象
    start = time.time()
    t1.start()   #启动线程t1
    t2.start()    #启动线程t2
    end=time.time()
    print(end-start)
    print('结束')

 

posted @ 2020-10-28 19:47  maday  阅读(65)  评论(0)    收藏  举报