python 多线程

来源:互联网 发布:图解网络硬件 百度云 编辑:程序博客网 时间:2024/06/06 17:29

进程、线程之间的关系

打个比方:如果有一个车间,车间里面有工人在工作。那么进程就相当于这个车间,而线程就相当于车间里面工作的工人。
是不是差不多明白点了。进程不能运行,它是一些资源的封装体,主要是cpu,io,内存资源,好比车间里的电和工具一样。每个进程要运行至少需要一个线程,这个线程就是主线程。线程是负责干具体的工作的。

单线程的例子:

import timedef eat(food):    print ("eat %s" %food)    print("start:", time.ctime())    time.sleep(2)    print (time.ctime())def play(name):    print ("play %s" %name)    time.sleep(5)    print (time.ctime())if __name__=="__main__":    eat("宫保鸡丁")    play("篮球")    print (time.ctime())结果:    eat 宫保鸡丁    start: Wed Nov 29 21:05:26 2017    Wed Nov 29 21:05:28 2017    play 篮球    Wed Nov 29 21:05:33 2017    Wed Nov 29 21:05:33 2017

定义一个吃和玩的例子。可以看到,程序的运行的总时间是等于所以时间之和。

多线程例子:

import timeimport threadingdef eat(food):    print ("eat %s" %food)    print ("start:",time.ctime())    time.sleep(2)    print ("eat",time.ctime())def play(name):    print ("play %s" %name)    time.sleep(5)    print ("play",time.ctime())t1 = threading.Thread(target=eat,args=("宫保鸡丁",))t2 = threading.Thread(target=play,args=("篮球",))if __name__=="__main__":    t1.start()       t2.start()    print ("main:",time.ctime())结果:    eat 宫保鸡丁    start: Wed Nov 29 20:58:48 2017    play 篮球    main: Wed Nov 29 20:58:48 2017    eat Wed Nov 29 20:58:50 2017    play Wed Nov 29 20:58:53 2017

可以看出,对比单线程。时间减少了2秒。
多线程的定义:

  • 导入threading类
  • t1 = threading.Thread(target=eat,args=(“宫保鸡丁”,)) 实例化Thread 类。target= 传入要执行的函数,args= 函数的参数。是一个元组。注意后面的逗号
  • t1.start() 运行这个线程

setDaemon守护线程

def eat(food):    print ("eat %s" %food)    time.sleep(2)    print ("eat",time.ctime())def play(name):    print ("play %s" %name)    time.sleep(5)    print ("play",time.ctime())threads = []t1 = threading.Thread(target=eat,args=("宫保鸡丁",))threads.append(t1)t2 = threading.Thread(target=play,args=("篮球",))threads.append(t2)if __name__=="__main__":    t1.setDaemon(True)    t1.start()    t2.setDaemon(True)    t2.start()    print ("main:",time.ctime()) 结果:    eat 宫保鸡丁    play 篮球    main: Thu Nov 30 09:46:38 2017

setDaemon是守护线程,就是守护着主线程。主线程退出子线程就跟着退出。
注意:setDaemon 在start之前

join等待子线程运行完再运行主线程

def eat(food):    print ("eat %s" %food)    time.sleep(2)    print ("eat",time.ctime())def play(name):    print ("play %s" %name)    time.sleep(5)    print ("play",time.ctime())threads = []t1 = threading.Thread(target=eat,args=("宫保鸡丁",))threads.append(t1)t2 = threading.Thread(target=play,args=("篮球",))threads.append(t2)if __name__=="__main__":    for t in threads:        t.start()    for t in threads:        t.join()    print ("main:",time.ctime())结果:eat 宫保鸡丁play 篮球eat Thu Nov 30 09:48:21 2017play Thu Nov 30 09:48:24 2017main: Thu Nov 30 09:48:24 2017

可以看到主线程的main 最后执行。这里用循环,让两个子线程同时运行,运行完毕再运行主线程

内存共享 + 线程锁

num = 1threads = []lock = threading.Lock()def add_num():    global num    lock.acquire()    num +=1    lock.release()    time.sleep(1)for i in range(500):    t = threading.Thread(target=add_num)    t.start()    threads.append(t)for t in threads:    t.join()print (num)结果:    501

内存共享是线程的一个特点,就是多个线程可以修改同一个内存数据。但是有时候会可能多个线程同时修改一个数据造成数据的不正确(在python2中出现过,不多。python3 没有出现)。为了保险起见可以在修改数据之前加一个锁(threading.Lock())。修改之后再释放锁来保证数据不会同时被多个线程占用。

threading.Event 线程事件(引用博友的代码了,写的挺好)

import threading,timeimport randomdef light():    if not event.isSet():        event.set() #wait就不阻塞 #绿灯状态    count = 0    while True:        if count < 10:            print('\033[42;1m--green light on---\033[0m')        elif count <13:            print('\033[43;1m--yellow light on---\033[0m')        elif count <20:            if event.isSet():                event.clear()            print('\033[41;1m--red light on---\033[0m')        else:            count = 0            event.set() #打开绿灯        time.sleep(1)        count +=1def car(n):    while 1:        time.sleep(random.randrange(10))        if  event.isSet(): #绿灯            print("car [%s] is running.." % n)        else:            print("car [%s] is waiting for the red light.." %n)if __name__ == '__main__':    event = threading.Event()    Light = threading.Thread(target=light)    Light.start()    for i in range(3):        t = threading.Thread(target=car,args=(i,))        t.start()

event = threading.Event() 实例化一个事件
event.isSet()判断是否为True
even.set() 设置为True
even.clear() 设置为False

我觉得event就是设置了一个全局变量,每个线程根据变量的真假做动作。上面代码改为全局变量模式

import threading,timeimport randomflag = Truedef light():    global flag    if not flag:        flag = True #wait就不阻塞 #绿灯状态    count = 0    while True:        if count < 10:            print('\033[42;1m--green light on---\033[0m')        elif count <13:            print('\033[43;1m--yellow light on---\033[0m')        elif count <20:            if flag:                flag = False            print('\033[41;1m--red light on---\033[0m')        else:            count = 0            flag=True #打开绿灯        time.sleep(1)        count +=1def car(n):    global flag    while 1:        time.sleep(random.randrange(10))        if  flag: #绿灯            print("car [%s] is running.." % n)        else:            print("car [%s] is waiting for the red light.." %n)if __name__ == '__main__':    #event = threading.Event()    Light = threading.Thread(target=light)    Light.start()    for i in range(3):        t = threading.Thread(target=car,args=(i,))        t.start()

多线程加queue实现生产者消费者模型。

模型简介:
生产者生产包子,消费者吃包子。如果生产者生产的慢,消费者吃得快。就会导致消费者的等待,在等待的过程中不能干别的事情。所以引入了queue,它就像一个桌子一样,生产完包子将包子放到桌子上,消费者直接去桌子上取。这样消费者不直接依赖生产者,也就实现了解耦。
上代码:

import queueimport threadingimport timeq = queue.Queue()def producer(name):    while True:        time.sleep(1)        q.put("包子")        print ("%s 做了一个包子" %name)        print (q.qsize())def comsumer(name):    while True:        time.sleep(2)        if not q.empty():            q.get()            print("%s 吃了一个包子" %name)for i in range(2):    t = threading.Thread(target=producer,args=("大壮",))    t.start()for i in range(3):    t = threading.Thread(target=comsumer,args=("小壮实",))    t.start()
原创粉丝点击