关于线程一个小细节

关于线程的一个小细节

使用单线程执行循环

这个脚本是在一个单线程中连续执行两个循环,而这必须是一个循环完了,再去执行另一个循环,总耗时为两个循环所用时间之和

#!/usr/bin/python
# -*-coding:utf-8-*-
# Author:Gsuhy

from time import sleep,ctime

def loop1():
    print('start loop 1 at: ',ctime())
    sleep(4)
    print('  done at: ',ctime())


def loop2():
    print('start loop 2 at: ', ctime())
    sleep(4)
    print('loop 2 done at: ', ctime())

def main():
    print('start at: ',ctime())
    loop1()
    loop2()
    print('all done at ',ctime())

if __name__ == '__main__':
    main()

 --------------------------
 start at:  Sat Sep  7 15:10:51 2019
start loop 1 at:  Sat Sep  7 15:10:51 2019
  done at:  Sat Sep  7 15:10:55 2019
start loop 2 at:  Sat Sep  7 15:10:55 2019
loop 2 done at:  Sat Sep  7 15:10:59 2019
all done at  Sat Sep  7 15:10:59 2019

可以看到,这里总用时8秒

而如果用的是thread模块的话,效果会有不同
注:thread(在python3中改名为_thread)

使用thread模块

thread模块提供了简单的多线程机制,那么两个循环就是并发执行的,也就是说运行的总时间跟最慢的那个有关,就不是两个循环总和了。

#!/usr/bin/python
# -*-coding:utf-8-*-
# Author:Gsuhy

import _thread
from time import sleep,ctime

def loop0():
    print('start loop0 at: ',ctime())
    sleep(4)
    print('loop0 done at: ',ctime())

def loop1():
    print('start loop1 at: ',ctime())
    sleep(3)
    print('loop1 done at: ',ctime())

def main():
    print('start time:',ctime())
    _thread.start_new_thread(loop0,())
    _thread.start_new_thread(loop1,())
    sleep(7)
    print('all done at: ',ctime())

if __name__ == '__main__':
    main()
----------------------
start time: Sat Sep  7 15:45:47 2019
start loop0 at:  Sat Sep  7 15:45:47 2019
start loop1 at:  Sat Sep  7 15:45:47 2019
loop1 done at:  Sat Sep  7 15:45:50 2019
loop0 done at:  Sat Sep  7 15:45:51 2019
all done at:  Sat Sep  7 15:45:54 2019

可以看到这里总时间变为了7s,睡眠 4 秒和睡眠 2 秒的代码片段是并发执行的,这样有助于减少整体的运行时间。你甚
至可以看到 loop 1 是如何在 loop 0 之前结束的。这个应用程序中剩下的一个主要区别是增加了一个 sleep(6)调用。为什么必须要这样做呢?这是因为如果我们没有阻止主线程继续执行,它将会继续执行下一条语句,显示“all done”然后退出,而loop0()loop1()这两个线程将直接终止。

而且这里还踩了一个坑,就是_thread.start_new_thread(loop0,())这个语句,开始并不是这样的,开始我还是像第一个脚本那样,在loop0方法后面加了括号,然后就在这一行报错first arg must be callable,后来上网查,都是些乱七八糟的回答,书上说:start_new_thread()必须包含开始的两个参数,于是即使要执行的函数不需要参数,也需
要传递一个空元组。 那么我想就应该不是后面那个()的问题,那可能就应该是方法问题,果不其然,把方法的括号去掉,就ok。

再修改一下代码,使用锁,除去单独的循环函数

使用线程和锁

#!/usr/bin/python
# -*-coding:utf-8-*-
# Author:Gsuhy

import _thread
from time import sleep,ctime

loops = [4,3]

def loop(nloop,nsec,lock):
    print('start loop ',nloop,'at:',ctime())
    sleep(nsec)
    print('loop ', nloop, 'done at:', ctime())
    lock.release()

def main():
    print('start time:',ctime())
    locks=[]
    nloops =range(len(loops))

    for i in nloops:
        lock = _thread.allocate_lock()
        lock.acquire()
        locks.append(lock)

    for i in nloops:
        _thread.start_new_thread(loop,(i,loops[i],locks[i]))

    for i in nloops:
        while locks[i].locked():
            pass
        print('all done at: ',ctime())

if __name__ == '__main__':
    main()
--------------------------
start time: Sun Sep  8 00:56:26 2019
start loop  1 at: Sun Sep  8 00:56:26 2019
start loop  0 at: Sun Sep  8 00:56:26 2019
loop  1 done at: Sun Sep  8 00:56:29 2019
loop  0 done at: Sun Sep  8 00:56:30 2019
all done at:  Sun Sep  8 00:56:30 2019

   转载规则


《关于线程一个小细节》 Gsuhy 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录