• 线程


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

  • 相关阅读:
    To select the file to upload we can use the standard HTML input control of type
    Cascading Menu Script using Javascript Explained
    网站首页head区代码规范
    轻松掌握 Java 泛型
    JDK 5.0 中的泛型类型学习
    如何在firefox下获取下列框选中option的text
    是同步方法还是 synchronized 代码? 详解多线程同步规则
    javascript select option对象总结
    Select的动态取值(Text,value),添加,删除。兼容IE,FireFox
    javascript在ie和firefox下的一些差异
  • 原文地址:https://www.cnblogs.com/zhouzhe-blog/p/9432188.html
Copyright © 2020-2023  润新知