Python如何创建线程,线程的用法包括哪些

Admin 2022-06-30 群英技术资讯 280 次浏览

这篇文章主要讲解了“Python如何创建线程,线程的用法包括哪些”,文中的讲解内容简单、清晰、详细,对大家学习或是工作可能会有一定的帮助,希望大家阅读完这篇文章能有所收获。下面就请大家跟着小编的思路一起来学习一下吧。


一、介绍

线程是什么?线程有啥用?线程和进程的区别是什么?

线程是操作系统能够进行运算调度的最小单位。被包含在进程中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

二、Python如何创建线程

2.1 方法一:

创建Thread对象

步骤:

1.目标函数

2.实例化Thread对象

3.调用start()方法

import threading


# 目标函数1
def fun1(num):
    for i in range(num):
        print('线程1: 第%d次循环:' % i)


# 目标函数2
def fun2(lst):
    for ele in lst:
        print('线程2: lst列表中元素 %d' % ele)


def main():
    num = 10
    # 实例化Thread对象
    # target参数一定为一个函数,且不带括号
    # args参数为元组类型,参数为一个时一定要加逗号
    t1 = threading.Thread(target=fun1, args=(num,))
    t2 = threading.Thread(target=fun2, args=([1, 2, 3, 4, 5],))

    # 调用start方法
    t1.start()
    t2.start()


if __name__ == '__main__':
    main()

2.2 方法二:

创建子类继承threading.Thread类

import threading
import os


class Person(threading.Thread):
    def run(self):
        self.sing(5)
        self.cook()

    @staticmethod
    def sing(num):
        for i in range(num):
            print('线程[%d]: The person sing %d song.' % (os.getpid(), i))

    @staticmethod
    def cook():
        print('线程[%d]:The person has cooked breakfast.' % os.getpid())


def main():
    p1 = Person()
    p1.start()

    p2 = Person()
    p2.start()


if __name__ == '__main__':
    main()

三、线程的用法

3.1 确定当前的线程

import threading
import time
import logging


def fun1():
    print(threading.current_thread().getName(), 'starting')
    time.sleep(0.2)
    print(threading.current_thread().getName(), 'exiting')


def fun2():
    # print(threading.current_thread().getName(), 'starting')
    # time.sleep(0.3)
    # print(threading.current_thread().getName(), 'exiting')
    logging.debug('starting')
    time.sleep(0.3)
    logging.debug('exiting')


logging.basicConfig(
    level=logging.DEBUG,
    format='[%(levelname)s] (%(threadName)-10s) %(message)s'
)


def main():
    t1 = threading.Thread(name='线程1', target=fun1)
    t2 = threading.Thread(name='线程2', target=fun2)
    t1.start()
    t2.start()


if __name__ == '__main__':
    main()

3.2 守护线程

区别

  •  普通线程:主线程等待子线程关闭后关闭
  • 守护线程:管你子线程关没关,主线程到时间就关闭

守护线程如何搞

  • 方法1:构造线程时传入dameon=True
  • 方法2:调用setDaemon()方法并提供参数True
import threading
import time
import logging


def daemon():
    logging.debug('starting')
    # 添加延时,此时主线程已经退出,exiting不会打印
    time.sleep(0.2)
    logging.debug('exiting')


def non_daemon():
    logging.debug('starting')
    logging.debug('exiting')


logging.basicConfig(
    level=logging.DEBUG,
    format='[%(levelname)s] (%(threadName)-10s) %(message)s'
)


def main():
    # t1 = threading.Thread(name='线程1', target=daemon)
    # t1.setDaemon(True)
    t1 = threading.Thread(name='线程1', target=daemon, daemon=True)
    t2 = threading.Thread(name='线程2', target=non_daemon)
    t1.start()
    t2.start()

    # 等待守护线程完成工作需要调用join()方法,默认情况join会无限阻塞,可以传入浮点值,表示超时时间
    t1.join(0.2)
    t2.join(0.1)


if __name__ == '__main__':
    main()

3.3 控制资源访问

目的:

Python线程中资源共享,如果不对资源加上互斥锁,有可能导致数据不准确。

import threading
import time


g_num = 0


def fun1(num):
    global g_num
    for i in range(num):
        g_num += 1
    print('线程1 g_num = %d' % g_num)


def fun2(num):
    global g_num
    for i in range(num):
        g_num += 1
    print('线程2 g_num = %d' % g_num)


def main():
    t1 = threading.Thread(target=fun1, args=(1000000,))
    t2 = threading.Thread(target=fun1, args=(1000000,))
    t1.start()
    t2.start()


if __name__ == '__main__':
    main()
    time.sleep(1)
    print('主线程 g_num = %d' % g_num)

互斥锁

import threading
import time


g_num = 0
L = threading.Lock()


def fun1(num):
    global g_num
    L.acquire()
    for i in range(num):
        g_num += 1
    L.release()
    print('线程1 g_num = %d' % g_num)


def fun2(num):
    global g_num
    L.acquire()
    for i in range(num):
        g_num += 1
    L.release()
    print('线程2 g_num = %d' % g_num)


def main():
    t1 = threading.Thread(target=fun1, args=(1000000,))
    t2 = threading.Thread(target=fun1, args=(1000000,))
    t1.start()
    t2.start()


if __name__ == '__main__':
    main()
    time.sleep(1)
    print('主线程 g_num = %d' % g_num)

互斥锁引发的另一个问题:死锁

死锁产生的原理:

import threading
import time


g_num = 0
L1 = threading.Lock()
L2 = threading.Lock()


def fun1():
    L1.acquire(timeout=5)
    time.sleep(1)
    L2.acquire()
    print('产生死锁,并不会打印信息')
    L2.release()
    L1.release()


def fun2():
    L2.acquire(timeout=5)
    time.sleep(1)
    L1.acquire()
    print('产生死锁,并不会打印信息')
    L1.release()
    L2.release()


def main():
    t1 = threading.Thread(target=fun1)
    t2 = threading.Thread(target=fun2)
    t1.start()
    t2.start()


if __name__ == '__main__':
    main()
    time.sleep(1)
    print('主线程 g_num = %d' % g_num)

如何避免产生死锁:

锁超时操作

import threading
import time


g_num = 0
L1 = threading.Lock()
L2 = threading.Lock()


def fun1():
    L1.acquire()
    time.sleep(1)
    L2.acquire(timeout=5)
    print('超时异常打印信息1')
    L2.release()
    L1.release()


def fun2():
    L2.acquire()
    time.sleep(1)
    L1.acquire(timeout=5)
    print('超时异常打印信息2')
    L1.release()
    L2.release()


def main():
    t1 = threading.Thread(target=fun1)
    t2 = threading.Thread(target=fun2)
    t1.start()
    t2.start()


if __name__ == '__main__':
    main()
    time.sleep(1)
    print('主线程 g_num = %d' % g_num)

现在大家对于Python如何创建线程,线程的用法包括哪些的内容应该都有一定的认识了吧,希望这篇能对大家有所帮助。最后,想要了解更多,欢迎关注群英网络,群英网络将为大家推送更多相关的文章。 群英智防CDN,智能加速解决方案

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

猜你喜欢

成为群英会员,开启智能安全云计算之旅

立即注册
专业资深工程师驻守
7X24小时快速响应
一站式无忧技术支持
免费备案服务
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
在线客服
微信公众号
返回顶部
返回顶部 返回顶部
在线客服
在线客服