zoukankan      html  css  js  c++  java
  • 线程

    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)
        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的重要的一个点!!

  • 相关阅读:
    day01的那些事
    Activity活动
    开始认真学习Android了
    《知其所以然》读书笔记
    网络编程——完成端口
    开发服务器端——工程配置
    完善自己的学习方法
    WSAAsyncSelect模型
    双缓冲绘图
    ListControl常用操作汇总
  • 原文地址:https://www.cnblogs.com/zhouzhe-blog/p/9432188.html
Copyright © 2011-2022 走看看