线程

1、启动一个线程

import threading
import time

def run(name):
    time.sleep(2)
    print('{name} is running the threading!!'.format(name = name))

if __name__ == '__main__':
    t = threading.Thread(target=run,args=('Chen',))
    t.start()
print('The main process is running!')

结果如下:

The main process is running!
Chen is running the threading!!

注:由此看出,线程启动后已与程序本身的线程(主线程)已经没有关系了,并不会等待主线程运行完毕后再运行手动启动的线程。

2、join()函数的意思是等调用该函数的实例线程运行完毕之后在运行主线程,例如在上边代码的基础上,在t.start()后边增加t.join(),则运行结果如下:

Chen is running the threading!!
The main process is running!

如果手动启动多个线程,要等所有的线程运行完毕后在运行主线程,则需要循环,如下:

import threading
import time

def run(name):
    time.sleep(4)
    print('{name} is running the threading!!'.format(name = name))
def run1(name):
    time.sleep(2)
    print('{name} is running the threading!!'.format(name = name))
    time.sleep(1)

if __name__ == '__main__':
   t1 = threading.Thread(target=run,args=('Chen',))
   t2 = threading.Thread(target=run1, args=('Chen2',))
   t1.start()
   t2.start()
   t2.join()

print('The main process is running!')

结果如下:

Chen2 is running the threading!!
The main process is running!
Chen is running the threading!!

模型如下:

 

3、如果要等所有的程序运行完毕之后在运行主程序,则需要遍历所有手动启动的线程

import threading
import time

def run1(name):
    time.sleep(4)
    print('{name} is running the threading!!'.format(name = name))
def run2(name):
    time.sleep(2)
    print('{name} is running the threading!!'.format(name = name))
    time.sleep(1)
def run3(name):
    time.sleep(2)
    print('{name} is running the threading!!'.format(name = name))
t_list = []
if __name__ == '__main__':
    t1 = threading.Thread(target=run1,args=('Chen1',))
    t2 = threading.Thread(target=run2,args=('Chen2',))
    t3 = threading.Thread(target=run3,args=('Chen3',))
    t1.start()
    t2.start()
    t3.start()
    t_list.append(t1)
    t_list.append(t2)
    t_list.append(t3)
    for t in t_list:
        t.join()

print('The main process is running!')

这样主程序就会等所有的手动线程启动完成之后才会运行!

4、daemon thread 守护线程,守护线程就是伴随着其他线程的消亡而自动消亡的,他的执行情况不重要

import threading
import time

def run(name):
    time.sleep(1)
    print('I am the child of daemon threading {name}'.format(name = name))

def main():
    print('The main threading is running!!')
    r = threading.Thread(target=run,args=('main',))
    r.start()
    time.sleep(2)  //这的时间大于run的时间,所以在main执行完后,run也执行完比,但当这的时间小于run()的时间,那么run()就没有执行完毕,即程序运行的结果为:The main threading is running和
//The threading has runned,就没有I am the child of daemon threading main了
if __name__ == '__main__': m = threading.Thread(target=main) m.setDaemon(True) //设置main为守护线程,当主线程执行完毕后,不管守护线程是否执行完毕,守护线程及子线程全部结束 m.start() //守护线程的设置一定要在线程开始之前设置(很正常的逻辑,小细节) m.join(timeout = 8) //这里的8sec表示最多不超过8s,当在小于8s的时间内守护线程运行完毕,主线程的运行时间可以小于8 print('The threading has runed
总结:守护线程是伴随其守护的线程而存亡的,当守护的线程结束时,守护线程及其子线程一并结束。

5.1、线程锁(互斥锁Mutex)

在同一个进程中,线程是共享空间的,当在同一个进程中启动多个线程时,而多个线程调用同一份数据时,此时就有可能出乱子了。例如:

import threading
import time

def run():
    global num
    time.sleep(1)
    lock.acquire()
    num -= 1
    lock.release()
    print('The result of num is:',num)

lock = threading.Lock()
num = 1000
t_list = []
if __name__ == '__main__':
    for i in range(1000):
        t = threading.Thread(target=run,args=())
        t.start()
        t_list.append(t)
    for t in t_list:
        t.join()

加锁的主要目的在于每一次只能有一个线程对数据进行修改,而不至于出现第一个线程还没运行结束,第二个线程就过来取数据,这样两个线程运行的结果是一样的。运算模型如下

5.2递归锁 就时在父线程中加锁,然后在子线程中也加锁

启动多个线程,每个线程调用同样的两个方法A和B,两种方法分别处理同一块数据,就有可能出现互斥锁的情况,故需要再增加一层锁,就称谓递归锁!!

5.3 信号量(semaphore):就是同时允许多少个线程对同一块数据进行处理。使用方法如下:

import threading, time
def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread: %s\n" % n)
    semaphore.release()
num = 0
semaphore = threading.BoundedSemaphore(5)  # 最多允许5个线程同时运行

if __name__ == '__main__':
    for i in range(20):
        t = threading.Thread(target=run, args=(i,))
        t.start()

5.4Timer

import threading
def hello():
    print("hello, world")
t = threading.Timer(10,hello)
t.start()  # after 30 seconds, "hello, world" will be printed

6、Event()事件,就好比两个人再对话一样,是一个时间,事件里边包括两个人。

import threading
import time

event = threading.Event()

def talk_1(name):
    count = 1
    event.set()   #设置的是讲话
    while True:
        if count <= 5:
            print('{name} is talking!!'.format(name = name))
        elif count > 5 and count <= 10:
            event.clear()
            print('我不讲了,我要看着你讲!!')
        else:
            count = 0
            event.set()
        count += 1
        time.sleep(1)

def talk_2(name):
    while True:
        if not event.isSet():
            print('{name} begin to talk!!'.format(name = name))
        else:
            event.wait()
            print('{name} is looking at Lilei!!'.format(name = 'Lucy'))
        time.sleep(1)

if __name__ == '__main__':
    t = threading.Thread(target=talk_1,args=('Lilei',))
    t.start()
    c = threading.Thread(target=talk_2,args=('Lucy',))
    c.start()

事件设置的是Lilei在讲话,Lucy在看着leilei讲话,讲完后,切换。event.wait()只有在事件被设置后才运行。

7、queue

queue有几种类型,先进先出,first in first out, 后进先出, last in first out, 还有一个优先权

import queue

q = queue.Queue()生成一个先进先出的queue

q = queue.Lifoqueue()生成一个后进先出的queue

q = queue.PriorityQueue(maxsize = internal)优先队列再生成实例是要求确定队列的大小,即需要确定maxsize的数值,压栈是需要确定队列的先后顺序例如:

q.put((1,20))

q.put((2,30))

q.put((0,50))把队列中第一个位置放50,第二个位置放20,第三个位置放30.

 消费者买包子模型,就是生产者不停的往蒸笼里放包子,做好的包子不断的被消费者购买,蒸笼的大小是不变的,这也是queue区别与list的重要的一个点!!

posted @ 2018-08-06 19:43  Elience  阅读(273)  评论(0编辑  收藏  举报