python多线程

什么是线程?
同进程下执行,并共享相同的上下文
线程间的信息共享和通信更加容易
多线程并发执行
需要同步原语

python多线程

_thread提供了基本的线程和锁

threading提供了更高级别的,功能更全面的线程管理: 支持同步机制 支付守护线程

thread模块的函数:
start_new_thread(funtion,args,kwargs(None))
allocate_lock()     分配lockType锁对象
exit()              线程退出指令
acquire(wait=None)  尝试获取锁对象
locked()            如果获得锁对象返回True,否则返回False
release()           释放锁
run()               使用者重写方法
join(timeout=None)  线程结束之前一直挂起,除非给出超时时间,否则会一直阻塞
getName()           返回线程名
setName(name)       设定线程名
isAlive/is_alive()  线程是否还存活
setDaemon(daemonic) 把线程的守护标志设定为布尔值daemonic,必需在线程start()之前调用(Daemon 译为后台程序)

举个例子:

import logging
from time import sleep, ctime

logging.basicConfig(level=logging.INFO)

# 写两个线程,分别执行
def test0():
    logging.info('开始test0,时间为' + ctime())
    sleep(2)
    logging.info('结束test0,时间为' + ctime())


def test1():
    logging.info('开始test1,时间为' + ctime())
    sleep(4)
    logging.info('结束test1,时间为' + ctime())


def main():
    logging.info('开启所有线程,时间为' + ctime())
    test0()
    test1()
    logging.info('结束所有进程,时间为' + ctime())


if __name__=='__main__':
    main()


"""运行结果为:
INFO:root:开启所有线程,时间为Sat Oct 29 22:54:28 2022
INFO:root:开始test0,时间为Sat Oct 29 22:54:28 2022
INFO:root:结束test0,时间为Sat Oct 29 22:54:30 2022
INFO:root:开始test1,时间为Sat Oct 29 22:54:30 2022
INFO:root:结束test1,时间为Sat Oct 29 22:54:34 2022
INFO:root:结束所有进程,时间为Sat Oct 29 22:54:34 2022
"""

如何使用_thread模块,代码如下:

import _thread
import logging
from time import sleep, ctime

logging.basicConfig(level=logging.INFO)


def test0():
    logging.info('开始test0,时间为' + ctime())
    sleep(2)
    logging.info('结束test0,时间为' + ctime())


def test1():
    logging.info('开始test1,时间为' + ctime())
    sleep(4)
    logging.info('结束test1,时间为' + ctime())


def main():
    logging.info('开启所有线程,时间为' + ctime())
    _thread.start_new_thread(test0, ())  # 这里传入的是函数,不要加括号
    _thread.start_new_thread(test1, ())  # 第二个参数是test1函数的参数,这里为空
    sleep(6)
    logging.info('结束所有进程,时间为' + ctime())


if __name__ == '__main__':
    main()

为什么一定要在main里面sleep(6)呢?

这就是_thread的弊端,如果不加sleep,主线程退出后,所有子线程都会被强行退出。它不会守护线程。但问题是我们不知道子线程需要运行多长时间。要解决这个问题需要用到lock锁,不过有点复杂,先不管。 

换个思路,咱们来使用threading,它自带的join方法,可以在线程没结束时进行阻塞。

最终代码:

import threading
import logging
from time import sleep, ctime

logging.basicConfig(level=logging.INFO)


# 写一个类去继承
class MyThread(threading.Thread):
    def __init__(self, func, args, func_name=''):
        """
        :param func: 函数
        :param args: 函数的参数
        :param func_name: 函数名(举例子)
        """
        threading.Thread.__init__(self)  # 主动去调用init方法
        self.args = args
        self.func = func
        self.func_name = func_name

    def run(self):  # 重写threading.Thread中的run方法
        self.func(*self.args)


tests = [3, 3]

def test(n, sec):
    """
    :param n: 线程数
    :param sec: 运行时间
    """
    logging.info('开始线程' + str(n) + ',时间为' + ctime())
    sleep(sec)
    logging.info('结束线程' + str(n) + ',时间为' + ctime())


def main():
    logging.info('开启所有线程,时间为' + ctime())
    threads = []
    ns = range(len(tests))
    for i in ns:
        t = MyThread(test, (i, tests[i]), test.__name__)
        threads.append(t)
    for i in ns:
        threads[i].start()
    for i in ns:
        threads[i].join()       # threading中自带的join方法,如果线程没结束则会阻塞
    logging.info('结束所有进程,时间为' + ctime())


if __name__ == '__main__':
    main()

运行结果为:

INFO:root:开启所有线程,时间为Sat Oct 29 23:52:28 2022
INFO:root:开始线程0,时间为Sat Oct 29 23:52:28 2022
INFO:root:开始线程1,时间为Sat Oct 29 23:52:28 2022
INFO:root:结束线程1,时间为Sat Oct 29 23:52:31 2022
INFO:root:结束线程0,时间为Sat Oct 29 23:52:31 2022
INFO:root:结束所有进程,时间为Sat Oct 29 23:52:31 2022

需要注意:线程1和2不一定哪个先结束。

多线程的应用场景:

比如app自动化测试中可能需要用到日志查询,日志输出是一个持续的过程,如果在操作结束后去抓日志,有可能抓不到关键信息,此时使用多线程,在操作之前就开始抓日志,一直持续到操作结束后的查询阶段,查询结束后再退出线程。确保能抓到关键信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值