day9线程和进程

进程:qq要以一个总体的形式暴露给操做系统管理,里面包含对各类资源的调用,内存的对各类资源管理的集合,就可称之为进程。python

线程:是操做系统最小的调度单位,是一串指令的集合。编程

进程:要操做CPU,必需要先建立一个线程,进程不能单独执行,进程执行是调动线程,至少要有一个线程;安全

进程是资源的集合,线程是最小的单位,全部速度没有可比性。启动线程快。多线程

线程共享内存空间,进程的内存是相互独立的。并发

同一个进程的线程之间能够直接交流,两个进程想通讯,必须经过一个中间代理来实现。app

建立新线程很简单,建立新进程须要对其父进程进行一次克隆。dom

一个线程能够控制和操做同一进程里的其余线程,可是进程只能操做子进程。函数

使用函数定义一个线程:ui

 

 
 
import threading,time

def func(num):
print("Runing on %s threading......" %num)
time.sleep(2)

if __name__ == "__main__":
start_time = time.time()
t1 = threading.Thread(target=func,args=(1,)) #生成一个线程t1实例
t2 = threading.Thread(target=func,args=(2,))

t1.start() #启动线程t1
t2.start()

print(t1.getName()) #获取线程名
print(t2.getName())

end_time = time.time()
spend_time = end_time - start_time
print("花费时间:",spend_time)

 

    上面代码,生成了一个线程,线程同时执行,若是正常状况下,确定先执行t1,而后执行t2,花费的时间是4秒以上,可是使用线程,执行之间只有两秒多,以下:spa

Runing on 1 threading......
Thread-1
Thread-2
花费时间: 0.0005929470062255859
Runing on 2 threading......

    因为上述代码是并行的,线程先执行,执行完成以后等待两秒。

使用类建立线程:

import threading,time

class MyThreading(threading.Thread):
    '''本身建立的类,继承的是线程的类,覆盖了以前的类,所以要重写父类'''
    def __init__(self,num):
        super(MyThreading,self).__init__()   #括号里面是加入参数的
        '''重写父类'''
        self.num = num

    def run(self):   #定义每一个函数运行的函数,类的全部方法在run中,调用run,必须是run函数
        print("Running task %s" %self.num)
        time.sleep(2)


if __name__ == "__main__":
    t3 = MyThreading(1)   #定义线程1
    t4 = MyThreading(2)

    t3.start()            #执行线程1
    t4.start()

    print(t3.getName())   #获取线程1的名字
    print(t4.getName())

    上面代码,是运用类建立的线程,super(MyThreading,self).__init__(),重写类,生成新的类,使用类建立线程,全部的方法必须定义在run()函数中。

    旧式类启用线程:

 
 
import threading,time

class MyThread(threading.Thread):
'''用旧式类生成线程'''
def __init__(self,num):
threading.Thread.__init__(self)
self.num = num

def run(self):
print("Start the %s threading......" %self.num)
time.sleep(2)


if __name__ == "__main__":
start_time = time.time() #程序执行起始时间
t5 = MyThread(1) #生成线程1实例
t6 = MyThread(2)

t5.start() #启动线程1
t6.start()

print(t5.getName()) #获取线程1名字
print(t6.getName()) #获取线程2名字

end_time = time.time() #程序执行结束时间
spend_time = end_time - start_time #程序执行花费时间
print(spend_time)
代码运行结果以下:
Start the 1 threading......
Start the 2 threading......
Thread-1
Thread-2
0.0004968643188476562

    上面使用旧式类写的类,启动线程。

    上面的花费时间,是启用线程的时间,并非程序执行的时间。上面的代码是并行运行的。

把线程编程串行执行,即一个线程执行完毕再继续执行下一个线程,以下:

import threading,time

class MyThread(threading.Thread):
    '''用旧式类生成线程'''
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num = num

    def run(self):
        print("Start the %s threading......" %self.num)
        time.sleep(2)


if __name__ == "__main__":
    start_time = time.time()  # 程序执行起始时间
    for i in range(5):
        t8 = MyThread(i)           #生成线程1实例
        t8.start()
        t8.join()                 #等待线程执行结果,这个线程没有执行完毕,程序不执行下一步,让线程执行变成并行

    end_time = time.time()     #程序执行结束时间
    spend_time = end_time - start_time   #程序执行花费时间
    print("--------all theads has finished----------------")
    print(spend_time)
运行结果以下:
Start the 0 threading......
Start the 1 threading......
Start the 2 threading......
Start the 3 threading......
Start the 4 threading......
--------all theads has finished----------------
10.011518001556396

    从结果能够看出,上面程序执行编程了串行,等待上一个线程执行完毕以后,才会执行下一个线程,只是在里面加入一个执行,t1.join(),用来让程序等待。

    下面咱们让两个线程等待执行的时间不必定,以下:

 
 
import threading,time

class MyThread(threading.Thread):
'''用旧式类生成线程'''
def __init__(self,num,execute_time):
threading.Thread.__init__(self)
self.num = num
self.execute_time = execute_time

def run(self):
print("Start the %s threading......" %self.num)
time.sleep(self.execute_time)
print("Threading %s task done!" %self.num)


if __name__ == "__main__":
start_time = time.time() # 程序执行起始时间
t1 = MyThread(1,2) #生成线程1实例
t2 = MyThread(2,4)
t1.start() #执行t1
t2.start() #执行t2
t1.join() #等待线程执行结果,这个线程没有执行完毕,程序不执行下一步,让线程执行变成并行

end_time = time.time() #程序执行结束时间
spend_time = end_time - start_time #程序执行花费时间
print("--------all theads has finished----------------")
print(spend_time)

程序执行以下:
Start the 1 threading......
Start the 2 threading......
Threading 1 task done!
--------all theads has finished----------------
2.0026450157165527
Threading 2 task done!

    上面程序中,线程t1和t2同时执行,可是t1.join()只等待第一个线程执行完毕,不会等待第二个线程执行完毕再往下执行,能够看出,程序向下执行完毕以后,t2还在等待执行过程当中。

    主线程问题,程序运行是有一个主线程在运行的。下面看一个实例:

import threading,time

class MyThread(threading.Thread):
    '''用旧式类生成线程'''
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num = num

    def run(self):
        print("Start the %s threading......" %self.num)
        time.sleep(4)
        print("Threaing %s task done!!!!" %self.num)


if __name__ == "__main__":
    start_time = time.time()  # 程序执行起始时间
    t_objs = []    #建立一个临时列表,先让线程都启动
    for i in range(50):
        t8 = MyThread(i)           #生成线程1实例
        t8.start()
        t_objs.append(t8)          #启动全部线程并添加列表中
        #print(t_objs)
    print("当前活跃的线程个数:",threading.active_count())
    for t in t_objs:
        t8.join()                 #全部线程启动执行完毕以后,等待全部线程执行完毕以后执行下一个线程

    end_time = time.time()     #程序执行结束时间
    print("--------all theads has finished----------------",threading.current_thread(),threading.active_count())
    spend_time = end_time - start_time   #程序执行花费时间
    print(spend_time)
运行结果以下:
Start the 0 threading......
Start the 1 threading......
Start the 2 threading......
Start the 3 threading......
Start the 4 threading......
Start the 5 threading......
Start the 6 threading......
Start the 7 threading......
Start the 8 threading......
Start the 9 threading......
Start the 10 threading......
Start the 11 threading......
Start the 12 threading......
Start the 13 threading......
Start the 14 threading......
Start the 15 threading......
Start the 16 threading......
Start the 17 threading......
Start the 18 threading......
Start the 19 threading......
Start the 20 threading......
Start the 21 threading......
Start the 22 threading......
Start the 23 threading......
Start the 24 threading......
Start the 25 threading......
Start the 26 threading......
Start the 27 threading......
Start the 28 threading......
Start the 29 threading......
Start the 30 threading......
Start the 31 threading......
Start the 32 threading......
Start the 33 threading......
Start the 34 threading......
Start the 35 threading......
Start the 36 threading......
Start the 37 threading......
Start the 38 threading......
Start the 39 threading......
Start the 40 threading......
Start the 41 threading......
Start the 42 threading......
Start the 43 threading......
Start the 44 threading......
Start the 45 threading......
Start the 46 threading......
Start the 47 threading......
Start the 48 threading......
当前活跃的线程个数: 51
Start the 49 threading......
Threaing 1 task done!!!!
Threaing 6 task done!!!!
Threaing 4 task done!!!!
Threaing 3 task done!!!!
Threaing 2 task done!!!!
Threaing 5 task done!!!!
Threaing 0 task done!!!!
Threaing 9 task done!!!!
Threaing 10 task done!!!!
Threaing 11 task done!!!!
Threaing 7 task done!!!!
Threaing 8 task done!!!!
Threaing 13 task done!!!!
Threaing 12 task done!!!!
Threaing 18 task done!!!!
Threaing 39 task done!!!!
Threaing 15 task done!!!!
Threaing 20 task done!!!!
Threaing 24 task done!!!!
Threaing 26 task done!!!!
Threaing 28 task done!!!!
Threaing 35 task done!!!!
Threaing 22 task done!!!!
Threaing 34 task done!!!!
Threaing 42 task done!!!!
Threaing 21 task done!!!!
Threaing 19 task done!!!!
Threaing 25 task done!!!!
Threaing 27 task done!!!!
Threaing 36 task done!!!!
Threaing 38 task done!!!!
Threaing 43 task done!!!!
Threaing 17 task done!!!!
Threaing 14 task done!!!!
Threaing 33 task done!!!!
Threaing 30 task done!!!!
Threaing 40 task done!!!!
Threaing 44 task done!!!!
Threaing 29 task done!!!!
Threaing 41 task done!!!!
Threaing 16 task done!!!!
Threaing 23 task done!!!!
Threaing 31 task done!!!!
Threaing 32 task done!!!!
Threaing 37 task done!!!!
Threaing 47 task done!!!!
Threaing 46 task done!!!!
Threaing 45 task done!!!!
Threaing 48 task done!!!!
Threaing 49 task done!!!!
--------all theads has finished---------------- <_MainThread(MainThread, started 139803255105280)> 1
4.0112504959106445

    上面程序中,咱们启动了50个线程,可是能够看出,实际上是由51个线程在执行,其中一个是线程自己,做为主线程,线程执行完毕以后,只剩下主线程,其余线程都被杀死,要先实现并行执行线程,全部线程同时启动,并等待上一个线程执行完毕,接着执行下一个线程,要借助列表,先生成一个空的列表,把全部生成的线程添加到列表中,而后再遍历列表,依次执行启动的线程。

    join()等待全部的线程执行完毕,主线程才继续执行。

    设置守护线程:

    正常状况下小,若是没有设置join(),程序会一直执行,不会管线程是否执行完毕,可是在主线程执行完毕以后,仍是会等待其余线程执行完毕,以下:

import threading,time

class MyThread(threading.Thread):
    '''用旧式类生成线程'''
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num = num

    def run(self):
        print("Start the %s threading......" %self.num)
        time.sleep(4)
        print("Threaing %s task done!!!!" %self.num)


if __name__ == "__main__":
    start_time = time.time()  # 程序执行起始时间
    t_objs = []    #建立一个临时列表,先让线程都启动
    for i in range(5):
        t8 = MyThread(i)           #生成线程1实例
        # t8.setDaemon(True)         #把当前线程设置为守护线程  ,必须在start以前
        '''程序会等待主线程执行完毕,守护线程执行完毕与否是无论的'''
        t8.start()
        t_objs.append(t8)          #启动全部线程并添加列表中
        #print(t_objs)
    print("当前活跃的线程个数:",threading.active_count())
    # for t in t_objs:
    #     t8.join()                 #全部线程启动执行完毕以后,等待全部线程执行完毕以后执行下一个线程

    end_time = time.time()     #程序执行结束时间
    print("--------all theads has finished----------------",threading.current_thread(),threading.active_count())
    spend_time = end_time - start_time   #程序执行花费时间
    print(spend_time)
运行结果以下:
Start the 0 threading......
Start the 1 threading......
Start the 2 threading......
Start the 3 threading......
Start the 4 threading......
当前活跃的线程个数: 6
--------all theads has finished---------------- <_MainThread(MainThread, started 139642438694656)> 6
0.0012087821960449219
Threaing 1 task done!!!!
Threaing 4 task done!!!!
Threaing 2 task done!!!!
Threaing 0 task done!!!!
Threaing 3 task done!!!

    从上面代码运行结果能够看出,主线程执行完毕以后,又执行了其余线程,程序在执行过程当中,启动了线程,可是不会在乎线程是否执行完毕,没有执行完毕就继续执行,可是最后会等待其余线程执行完毕以后结束程序。如何让主线程执行完毕以后,不等待其余线程是否执行完毕就结束线程呢?这里就要用到守护线程了,以下:

import threading,time

class MyThread(threading.Thread):
    '''用旧式类生成线程'''
    def __init__(self,num):
        threading.Thread.__init__(self)
        self.num = num

    def run(self):
        print("Start the %s threading......" %self.num)
        time.sleep(4)
        print("Threaing %s task done!!!!" %self.num)


if __name__ == "__main__":
    start_time = time.time()  # 程序执行起始时间
    t_objs = []    #建立一个临时列表,先让线程都启动
    for i in range(5):
        t8 = MyThread(i)           #生成线程1实例
        t8.setDaemon(True)         #把当前线程设置为守护线程  ,必须在start以前
        '''程序会等待主线程执行完毕,守护线程执行完毕与否是无论的'''
        t8.start()
        t_objs.append(t8)          #启动全部线程并添加列表中
        #print(t_objs)
    print("当前活跃的线程个数:",threading.active_count())
    # for t in t_objs:
    #     t8.join()                 #全部线程启动执行完毕以后,等待全部线程执行完毕以后执行下一个线程

    end_time = time.time()     #程序执行结束时间
    print("--------all theads has finished----------------",threading.current_thread(),threading.active_count())
    spend_time = end_time - start_time   #程序执行花费时间
    print(spend_time)
运行结果以下:
Start the 0 threading......
Start the 1 threading......
Start the 2 threading......
Start the 3 threading......
Start the 4 threading......
当前活跃的线程个数: 6
--------all theads has finished---------------- <_MainThread(MainThread, started 140133686212352)> 6
0.0010912418365478516

    上面程序把全部其余线程都设置成为了守护线程,t8.setDaemon(),设置守护线程,设置守护线程必须在start()线程开始以前设置,设置完毕以后,从结果能够看出,主线程执行完毕以后,就结束了程序,不会管其余线程是否执行完毕。

    全局解释器锁

    Python GIL(Global Interpreter Lock)

    In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

    上面的核心意思就是,不管你启多少个线程,你有多少个cpu, Python在执行的时候会淡定的在同一时刻只容许一个线程运行,擦。。。,那这还叫什么多线程呀?莫如此早的下结结论,听我现场讲。  

    首先须要明确的一点是GIL并非Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。就比如C++是一套语言(语法)标准,可是能够用不一样的编译器来编译成可执行代码。有名的编译器例如GCC,INTEL C++,Visual C++等。Python也同样,一样一段代码能够经过CPython,PyPy,Psyco等不一样的Python执行环境来执行。像其中的JPython就没有GIL。然而由于CPython是大部分环境下默认的Python执行环境。因此在不少人的概念里CPython就是Python,也就想固然的把GIL归结为Python语言的缺陷。因此这里要先明确一点:GIL并非Python的特性,Python彻底能够不依赖于GIL。

    python的线程是调用操做系统的原生线程,Python调用C语言的原生接口。

  线程锁(互斥锁Mutex)   

    一个进程下能够启动多个线程,多个线程共享父进程的内存空间,也就意味着每一个线程能够访问同一份数据,此时,若是2个线程同时要修改同一份数据,会出现什么情况?

import time
import threading


def addNum():
    global num  # 在每一个线程中都获取这个全局变量
    print('--get num:', num)
    time.sleep(1)
    num += 1  # 对此公共变量进行-1操做


num = 0  # 设定一个共享变量
thread_list = []
for i in range(50):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)
time.sleep(1.000001)

# for t in thread_list:  # 等待全部线程执行完毕
#     t.join()

print('final num:', num)
运行程序以下:
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
--get num: 0
final num: 49

    上面代码,执行结果有时候是50,有时候是49,如何解决呢?

    用户加锁,用户加锁确保同一时间只有一个线程在修改数据,上面的代码,若是在规定时间内,没有执行完毕,那么将释放GIL,让其余线程执行,形成过多修改同一数据,所以要用户本身加锁,确保同一时间只有一个线程修改数据。

import time
import threading


def addNum():
    global num  # 在每一个线程中都获取这个全局变量
    print('--get num:', num)

    lock.acquire()    #获取一把锁
    time.sleep(1)     #在所里面sleep()会把程序编程串行
    num += 1  # 对此公共变量进行-1操做
    lock.release()

num = 0  # 设定一个共享变量
thread_list = []
lock = threading.Lock()
for i in range(10):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)

for t in thread_list:  # 等待全部线程执行完毕
    t.join()

print('final num:', num)

    加锁,首先声明一把锁,lock=threading.Thread(target=addNum),生成一把锁,而后在函数中加锁,lock.acquire(),加锁,lock.release(),最后释放锁,把加的锁进行释放,为何要加锁呢?由于线程执行的时候,是有实现限制的,在规定时间若是为执行完毕,GIF会释放,加锁是为了让在同一时间内,只有同一个线程执行程序。

    加锁版本

import time
import threading


def addNum():
    global num  # 在每一个线程中都获取这个全局变量
    print('--get num:', num)
    time.sleep(1)
    lock.acquire()  # 修改数据前加锁
    num -= 1  # 对此公共变量进行-1操做
    lock.release()  # 修改后释放


num = 100  # 设定一个共享变量
thread_list = []
lock = threading.Lock()  # 生成全局锁
for i in range(100):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)

for t in thread_list:  # 等待全部线程执行完毕
    t.join()

print('final num:', num)

    递归锁(嵌套锁)----RLock(递归锁)

    说白了就是在一个大锁中还要再包含子锁   

    下面来看一个实例:

import threading, time


def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num


def run2():
    print("grab the second part data")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2


def run3():
    lock.acquire()    #第一道锁加锁,首先进入此锁
    res = run1()      #进入第二道锁,第二道也有锁
    print('--------between run1 and run2-----')
    res2 = run2()     #平行进入第二道锁,和上面run1是并行锁
    lock.release()
    print(res, res2)


if __name__ == '__main__':

    num, num2 = 0, 0
    lock = threading.Lock()
    for i in range(10):
        t = threading.Thread(target=run3)
        t.start()

while threading.active_count() != 1:
    print(threading.active_count())
else:
    print('----all threads done---')
    print(num, num2)

    上面代码是一把大锁里面嵌套一把小锁,这样会形成什么问题呢?以下:

11
11
11
11
11
11
......

    上面代码执行陷入了一个死循环,程序不停的执行,为何呢?

    递归锁--RLock:防止锁死

import threading, time


def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num


def run2():
    print("grab the second part data")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2


def run3():
    lock.acquire()    #第一道锁加锁,首先进入此锁
    res = run1()      #进入第二道锁,第二道也有锁
    print('--------between run1 and run2-----')
    res2 = run2()     #平行进入第二道锁,和上面run1是并行锁
    lock.release()
    print(res, res2)


if __name__ == '__main__':

    num, num2 = 0, 0
    lock = threading.RLock()
    for i in range(10):
        t = threading.Thread(target=run3)
        t.start()

while threading.active_count() != 1:
    print(threading.active_count())
else:
    print('----all threads done---')
    print(num, num2)
运行结果以下:
grab the first part data
--------between run1 and run2-----
grab the second part data
1 1
grab the first part data
--------between run1 and run2-----
grab the second part data
2 2
grab the first part data
--------between run1 and run2-----
grab the second part data
3 3
grab the first part data
--------between run1 and run2-----
grab the second part data
4 4
grab the first part data
--------between run1 and run2-----
grab the second part data
5 5
grab the first part data
--------between run1 and run2-----
grab the second part data
6 6
grab the first part data
--------between run1 and run2-----
grab the second part data
7 7
grab the first part data
--------between run1 and run2-----
grab the second part data
8 8
grab the first part data
--------between run1 and run2-----
grab the second part data
9 9
grab the first part data
2
--------between run1 and run2-----
grab the second part data
10 10
----all threads done---
10 10

    从上面代码能够看出,使用RLokc()递归所可以正确的执行退出。因此加锁屡次的时候,为了防止锁死,应该使用递归锁。

  Semaphore(信号量)

    互斥锁 同时只容许一个线程更改数据,而Semaphore是同时容许必定数量的线程更改数据 ,好比厕全部3个坑,那最多只容许3我的上厕所,后面的人只能等里面有人出来了才能再进去。

    Semaphore(信号量)同一时间只容许必定数量的线程更改数据。

import threading, time


def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread: %s\n" % n)
    semaphore.release()


if __name__ == '__main__':

    semaphore = threading.BoundedSemaphore(5)  # 最多容许5个线程同时运行
    '''每出来一个就会补充一个进去,限制线程里面只有必定数量的线程在执行,确保同一时间只有五个并发执行'''
    for i in range(17):
        t = threading.Thread(target=run, args=(i,))
        t.start()

while threading.active_count() != 1:
    pass  # print threading.active_count()
else:
    print('----all threads done---')
运行结果以下:
run the thread: 0
run the thread: 3
run the thread: 4

run the thread: 1

run the thread: 2



run the thread: 7
run the thread: 8

run the thread: 6

run the thread: 5


run the thread: 9

run the thread: 10
run the thread: 14

run the thread: 11

run the thread: 12
run the thread: 13



run the thread: 16
run the thread: 15


----all threads done---

    上面代码中,限定了同一时间执行的线程个数,semaphore=threading.BoundedSemaphore(5)规定同一时间只有5个线程在执行,当里面有线程执行完毕以后,就会有新的线程补充进来,知道全部线程都执行完毕。

    Events(事件)

    事件:状态的切换,每一次状态的切换会致使其余的变化,如红绿灯。

    时间:是一个很是简单的事件同步对象;一个事件须要一个内部标志。

    event = threading.Event()    #声明一个event()对象

    event.set()                  #设置一个全局变量,即标志位

    event.clear()                #清空标志位

    event.set()至关于True,event.clear()至关于False。

    event.wait()检测标志位是否设置,若是没有设置,会一直卡在哪里,不往下走。若是标志位设置则不会堵塞,wait()等待标志位被设置。

    If the flag is set, the wait method doesn’t do anything.

    标志位设定了,表明绿灯,直接通行。
  If the flag is cleared, wait will block until it becomes set again.

    标志位被清空,表明红灯,wait()等待变路灯。
  Any number of threads may wait for the same event.

    每一个线程均可以等待同一个事件。

    下面来写一个红绿灯的事件:

  经过Event来实现两个或多个线程间的交互,下面是一个红绿灯的例子,即起动一个线程作交通指挥灯,生成几个线程作车辆,车辆行驶按红灯停,绿灯行的规则。

import threading,time
import random
def 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 +=1
def 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()

    红绿灯:

import threading,time

event = threading.Event()   #声明一个event事件对象

def lighter():
    count = 0
    event.set()
    while True:
        if count > 20 and count < 30:    #改为红灯
            event.clear()     #把标志位清空
            print("\033[41;1mred light is on.......\033[0m")
        elif count > 30:
            event.set()       #设置标志位,变绿灯

            count = 0     #变成绿灯以后从新计数
        else:
            print("\033[42;1mgreen linght in on ......\033[0m")

        time.sleep(1)
        count += 1

def car(name):
    while True:    #检测标志位,存在则是绿灯,通行
        if event.is_set():     #若是设置了标志位,表明绿灯
            print("[%s] running ....." %name)
            time.sleep(1)
        else:
            print("[%s] sees red light,waiting please......." %name)
            event.wait()     #等待,标志位不存在,则等待标志位从新设定
            print("\033[34;1m[%s] green light in on ,start going ......\033[0m" %name)

light = threading.Thread(target=lighter)
light.start()

car1 = threading.Thread(target=car,args=("tesla",))
car1.start()

    上面代码就是实现了一个红绿灯的程序,程序运行结果以下:

green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
[tesla] running .....
green linght in on ......
green linght in on ......
[tesla] running .....
[tesla] running .....
green linght in on ......
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
green linght in on ......
[tesla] running .....
red light is on.......
[tesla] sees red light,waiting please.......
red light is on.......
red light is on.......
red light is on.......
red light is on.......
red light is on.......
red light is on.......
red light is on.......
red light is on.......
green linght in on ......
[tesla] green light in on ,start going ......
[tesla] running .....
green linght in on ......

    上面程序,实现了简单的红绿灯交替状况。

    queue队列  

 

    Python中,队列是线程间最经常使用的交换数据的形式。Queue模块是提供队列操做的模块,虽然简单易用,可是不当心的话,仍是会出现一些意外。

    queue是实现线程间信息的安全交换。

    建立一个“队列”对象
  import Queue
  q = Queue.Queue(maxsize = 10)
  Queue.Queue类便是一个队列的同步实现。队列长度可为无限或者有限。可经过Queue的构造函数的可选参数maxsize来设定队列长度。若是maxsize小于1就表示队列长度无限。 

  队列能够设置长度,maxsize=n,设置最大元素个数,使用put()添加数据,当超过maxsize以后,会形成卡顿。以下:

import queue

q = queue.Queue(maxsize=4)
q.put("alex")
q.put("wupeiqi")
q.put("sfasfd")
q.put("sb")
q.put("sdfasfd")
print(q.qsize())

    上面代码中,定义了队列的大小,只能放入4个元素,当咱们放过多的时候,形成卡顿。

import queue

q = queue.Queue(maxsize=4)
q.put("alex")
q.put("wupeiqi")
q.put("sfasfd")
q.put("sb")
print(q.qsize())

q.get()
q.get()
q.get()
q.get()

    使用get()获取数据,若是get()超过限制,就会形成卡顿,由于实在等待数据的存放,队列一直是在等待数据的存取。

    队列的集中方式:

  queue.Queue(maxsize)                #先入先出

    queue.LifoQueue(maxsize)            #last in first out后进先出

    queue.PriorityQueue(maxsize=0)      #存储数据可设置优先级的队列。   

    队列中的方法:

    q.get_nowait()若是没有数据取,会报一个异常。

    q.qsize()判断队列的长度。

    q.qsize()

    q.empty()   #判断队列是不是空的

  q.full()   #判断队列是否存放满了

  q.put(item,block=True,timeout=None)   block=True当queue满的时候,会卡主,False则会异常;timeout=None设置卡主多久报异常。

    优先级的queue,queue.PriorityQueue(maxsize=0)

 

import queue

q = queue.PriorityQueue()
q.put((10,"alex"))
q.put((-1,"chenronghua"))
q.put((9,"alex"))
q.put((6,"wangsong"))

print(q.get())
print(q.get())
print(q.get())
print(q.get())
运行结果以下:
(-1, 'chenronghua')
(6, 'wangsong')
(9, 'alex')
(10, 'alex')

 

    从上面代码能够看出,是按照顺序进行了排序,优先级的queue常常在一些会员登记里面使用,好比银行的叫号系统,是VIP优先的。

    生产者消费者模型

  在并发编程中使用生产者和消费者模式可以解决绝大多数并发问题。该模式经过平衡生产线程和消费线程的工做能力来提升程序的总体处理数据的速度。

    为何要使用生产者和消费者模式

 

    在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,若是生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。一样的道理,若是消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题因而引入了生产者和消费者模式。

    什么是生产者消费者模式

    生产者消费者模式是经过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通信,而经过阻塞队列来进行通信,因此生产者生产完数据以后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就至关于一个缓冲区,平衡了生产者和消费者的处理能力。

import queue,threading,time

q = queue.Queue(maxsize=10)                              #生成一个队列实例
def Producer(name):
    count = 1
    while True:
        time.sleep(0.2)
        q.put("骨头%i" %count)
        print("[%s]生成了[%s]骨头......"  %(name,count))
        count += 1

def Consumer(name):
    while True :
        time.sleep(1)
        print("[%s] 取到[%s],而且吃了它......" %(name,q.get()))

p = threading.Thread(target=Producer,args=("alex",))
c = threading.Thread(target=Consumer,args=("chenronghua",))
c1 = threading.Thread(target=Consumer,args=("王松",))

p.start()
c.start()
c1.start()

    上面代码实现了生产者和消费者的基本模型。

    代码运行结果以下:

[alex]生成了[1]骨头......
[alex]生成了[2]骨头......
[alex]生成了[3]骨头......
[alex]生成了[4]骨头......
[chenronghua] 取到[骨头1],而且吃了它......
[alex]生成了[5]骨头......
[王松] 取到[骨头2],而且吃了它......
[alex]生成了[6]骨头......
[alex]生成了[7]骨头......
[alex]生成了[8]骨头......
[alex]生成了[9]骨头......
[chenronghua] 取到[骨头3],而且吃了它......
[王松] 取到[骨头4],而且吃了它......
[alex]生成了[10]骨头......
[alex]生成了[11]骨头......
[alex]生成了[12]骨头......
[alex]生成了[13]骨头......
[alex]生成了[14]骨头......
[chenronghua] 取到[骨头5],而且吃了它......
[王松] 取到[骨头6],而且吃了它......
[alex]生成了[15]骨头......
相关文章
相关标签/搜索