Python多线程使用技巧(同步 + 异步 + 强制结束多线程)

多线程同步(函数化)

代码如下:

"""
多线程同步(函数化)
"""
# -*- coding:utf-8 -*-
import threading
import datetime
import time

__author__ = 'Evan'
locks = None
thread_pool = None


def unit_test(sleep_time):
    """
    多线程单元测试
    :param sleep_time: 睡眠时间
    :return:
    """
    # locks.acquire()   获取锁 -- 获取锁之后,其他的线程在此等待

    with thread_pool:  # 使用线程池控制多线程进入的数量,超过限定数量在此阻塞
        print('current thread name {}'.format(threading.current_thread().name))  # 当前线程名
        print('{} --> start sleep_time ({})'.format(datetime.datetime.now(), sleep_time))
        time.sleep(sleep_time)
        print('{} --> sleep_time ({}) finish'.format(datetime.datetime.now(), sleep_time))

    # locks.release()   释放锁 -- 如果不释放锁,后续的线程会一直被阻塞不能进入


def thread_run(sleep_list):
    """
    执行多线程
    :param sleep_list: 睡眠时间列表
    :return:
    """
    global locks, thread_pool

    locks = threading.Lock()  # 线程锁
    max_value = 3  # 设置可同时执行的最大线程数为3
    thread_pool = threading.Semaphore(value=max_value)  # 初始化线程池
    print('线程池最大数量:{}'.format(max_value))

    threads = []
    for i in sleep_list:  # 配置所有线程
        t = threading.Thread(target=unit_test, args=(i,))
        threads.append(t)

    for thread in threads:  # 开启所有线程
        thread.start()
        while True:
            # 判断正在运行的线程数量, 控制执行的线程数量永远为4-1=3个
            if len(threading.enumerate()) <= 4:
                # threading.enumerate()包括主线程和所有的活动子线程,长度最少为1
                print('剩余活动线程数量: {}'.format(len(threading.enumerate())))
                break

    # TODO thread.join()和下面的while循环都可阻塞所有线程,依据情况进行选择
    # for thread in threads:  # 主线程在此阻塞,等待所有线程结束
    #     thread.join()

    while True:
        # 当线程数量等于1时,并且只剩下一个主线程,退出循环
        if len(threading.enumerate()) == 1 and 'MainThread(MainThread' in str(threading.enumerate()[0]):
            break

    print('所有线程执行结束')


def main():
    thread_run(sleep_list=[3, 2, 6, 1, 7, 5, 8])


if __name__ == '__main__':
    main()

执行结果:

线程池最大数量:3
current thread name Thread-1剩余活动线程数量: 2

2020-04-16 17:37:40.504859 --> start sleep_time (3)
current thread name Thread-2剩余活动线程数量: 3

2020-04-16 17:37:40.504859 --> start sleep_time (2)
current thread name Thread-3剩余活动线程数量: 4

2020-04-16 17:37:40.511841 --> start sleep_time (6)
2020-04-16 17:37:42.512497 --> sleep_time (2) finish
剩余活动线程数量: 4
current thread name Thread-4
2020-04-16 17:37:42.512497 --> start sleep_time (1)
2020-04-16 17:37:43.510862 --> sleep_time (3) finish2020-04-16 17:37:43.516815 --> sleep_time (1) finish
剩余活动线程数量: 4

current thread name Thread-5
2020-04-16 17:37:43.516815 --> start sleep_time (7)
current thread name Thread-6
剩余活动线程数量: 4
2020-04-16 17:37:43.516815 --> start sleep_time (5)
2020-04-16 17:37:46.529807 --> sleep_time (6) finish
current thread name Thread-7
2020-04-16 17:37:46.535790 --> start sleep_time (8)
剩余活动线程数量: 4
2020-04-16 17:37:48.523479 --> sleep_time (5) finish
2020-04-16 17:37:50.523099 --> sleep_time (7) finish
2020-04-16 17:37:54.542362 --> sleep_time (8) finish
所有线程执行结束

多线程同步(使用父类继承方法)

代码如下:

"""
多线程同步(使用父类继承方法)
"""
# -*- coding:utf-8 -*-
import threading
import time
import datetime

__author__ = 'Evan'


class Test(threading.Thread):  # 继承threading.Thread类

    def __init__(self, sleep_time, thread_pool):
        super().__init__()  # 执行父类的构造方法
        self.sleep_time = sleep_time
        self.thread_pool = thread_pool  # 线程池句柄

    def run(self):
        """
        改写父类run方法,需要执行的多线程函数写在这里
        :return:
        """
        print('current thread name {}'.format(threading.current_thread().name))  # 当前线程名
        print('{} --> start sleep_time ({})'.format(datetime.datetime.now(), self.sleep_time))
        time.sleep(self.sleep_time)
        print('{} --> sleep_time ({}) finish'.format(datetime.datetime.now(), self.sleep_time))
        self.thread_pool.release()  # 释放线程锁,可用线程数加1


if __name__ == '__main__':
    max_value = 4
    pool = threading.Semaphore(value=max_value)  # 线程池(设置可同时执行的最大线程数为4)
    print('线程池最大数量:{}'.format(max_value))

    for i in [3, 2, 6, 1, 7]:
        pool.acquire()  # 获得线程锁,可用线程数减1
        t = Test(sleep_time=i, thread_pool=pool)  # 实例化线程类
        t.start()  # 开启线程(线程会自动执行run方法)

执行结果:

线程池最大数量:4
current thread name Thread-1
2020-02-24 12:57:52.198842 --> start sleep_time (3)
current thread name Thread-2
2020-02-24 12:57:52.199840 --> start sleep_time (2)
current thread name Thread-3
2020-02-24 12:57:52.199840 --> start sleep_time (6)
current thread name Thread-4
2020-02-24 12:57:52.199840 --> start sleep_time (1)
2020-02-24 12:57:53.200647 --> sleep_time (1) finish
current thread name Thread-5
2020-02-24 12:57:53.202368 --> start sleep_time (7)
2020-02-24 12:57:54.200846 --> sleep_time (2) finish
2020-02-24 12:57:55.199718 --> sleep_time (3) finish
2020-02-24 12:57:58.200735 --> sleep_time (6) finish
2020-02-24 12:58:00.202727 --> sleep_time (7) finish

多线程异步

代码如下:

"""
多线程异步
"""
# -*- coding:utf-8 -*-
import time
import datetime
from concurrent.futures import ThreadPoolExecutor

__author__ = 'Evan'


def unit_test(sleep_time):
    """
    多线程单元测试
    :param sleep_time: 睡眠时间
    :return:
    """
    print('{} --> start sleep_time ({})'.format(datetime.datetime.now(), sleep_time))
    time.sleep(sleep_time)
    print('{} --> sleep_time ({}) finish'.format(datetime.datetime.now(), sleep_time))


def main():
    max_value = 4  # 线程池最大数量
    thread_pool = ThreadPoolExecutor(max_workers=max_value)  # 初始化线程池
    print('线程池最大数量:{}'.format(max_value))

    # 异步多线程运行不会阻塞主线程,异步线程队列满了后会继续往下运行主线程,等队列释放后又回到异步线程继续执行
    for i in [3, 2, 6, 1, 7]:
        thread_pool.submit(unit_test, i)
    print('{} --> 我是主线程'.format(time.ctime()))


if __name__ == '__main__':
    main()

执行结果:

线程池最大数量:4
2020-02-24 13:00:35.349155 --> start sleep_time (3)
2020-02-24 13:00:35.349155 --> start sleep_time (2)
2020-02-24 13:00:35.350151 --> start sleep_time (6)
2020-02-24 13:00:35.350151 --> start sleep_time (1)
Mon Feb 24 13:00:35 2020 --> 我是主线程
2020-02-24 13:00:36.351237 --> sleep_time (1) finish
2020-02-24 13:00:36.351237 --> start sleep_time (7)
2020-02-24 13:00:37.350428 --> sleep_time (2) finish
2020-02-24 13:00:38.350457 --> sleep_time (3) finish
2020-02-24 13:00:41.351857 --> sleep_time (6) finish
2020-02-24 13:00:43.352244 --> sleep_time (7) finish

强制结束多线程

代码如下:

"""
强制结束线程方法:
1> 使用stop_thread函数关闭指定的单个线程
2> 设置当前函数为守护进程,函数结束后会关闭所有的子线程 --> Set daemon=True
"""
# -*- coding:utf-8 -*-
import threading
import time
import inspect
import ctypes


def stop_thread(tid, exctype=SystemExit):
    tid = ctypes.c_long(tid.ident)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("Invalid thread id")
    elif res != 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


def use_stop_thread_function():
    def test_1():
        while True:
            print('-------')
            time.sleep(1)

    print('Use stop thread function')
    t = threading.Thread(target=test_1)
    t.start()
    time.sleep(5)
    stop_thread(tid=t)
    print('Threads have been stopped')


class UseDaemonFunction(object):

    def test_2(self, times):
        time.sleep(times)
        print('times: {}'.format(times))

    def main(self):
        # 设置主线程
        self.threads = threading.Thread(target=self._main, args=())
        self.threads.start()

    def _main(self):
        print('Use daemon function')
        threads = []
        for i in range(20):
            # 开启20个子线程
            t = threading.Thread(target=self.test_2, args=(i, ))
            t.daemon = True  # 设置当前函数为守护进程
            threads.append(t)

        for i in threads:
            i.start()

        for i in threads:
            i.join()
        print('Threads have been stopped')


if __name__ == "__main__":
    # use_stop_thread_function()
    # ————分割线————
    use_daemon_funcion = UseDaemonFunction()
    use_daemon_funcion.main()  # 执行20个子线程

    time.sleep(5)
    # 杀死主线程,所有的子线程都会被关闭
    stop_thread(tid=use_daemon_funcion.threads)
    print('All done')

执行结果:

Use daemon function
times: 0
times: 1
times: 2
times: 3
times: 4
All done
times: 5

Over~在这里插入图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 库是否可行? 可以回答这个问题。Python 多线程调用异步库是可行的,但需要注意线程安全问题。异步库本身是为了解决 I/O 密集型任务而设计的,多线程可以提高 CPU 密集型任务的效率,但需要注意避免多线程之间的资源竞争和死锁等问题。建议使用 Python 的协程库 asyncio 来实现异步编程,同时使用 threading 或 multiprocessing 来实现多线程或多进程。 ### 回答2: Python可以通过多线程调用异步操作来提高程序的并发能力和响应速度。 在Python,可以使用`threading`模块来创建和管理多线程多线程是一种并发执行的方式,它允许多个线程在同一时间内执行不同的任务。 同时,Python也支持异步编程,可以通过`asyncio`模块来进行异步操作。异步操作可以在等待某些IO操作完成时,让出CPU资源给其他任务,以提高效率。 我们可以将异步操作放在一个线程进行执行。具体步骤如下: 1. 使用`threading`模块创建一个线程对象,并指定一个函数为线程的执行体。 2. 在该函数使用`asyncio`模块的相关方法来定义和执行异步操作,比如使用`async`关键字定义异步函数,使用`await`关键字阻塞等待异步操作的完成。 3. 启动线程,开始执行异步操作。 这样,我们就可以在一个线程同时执行多个异步操作,提高程序的并发能力。 需要注意的是,由于Python的全局解释锁(GIL)的存在,使得多线程无法真正实现并行执行。因此,通过多线程调用异步来提高程序的性能,主要是通过异步操作的非阻塞特性来实现任务的并发执行,而不是真正的并行执行。 总结起来,Python通过多线程调用异步可以提高程序的并发能力和响应速度,但需要注意多线程无法真正实现并行执行的限制。 ### 回答3: Python多线程调用异步可以通过一些库和技巧来实现。 首先,要注意Python的全局解释器锁(GIL),它会限制同一时间只能有一个线程在解释器执行Python字节码。因此,Python多线程并不能真正实现并行计算,但可以用于处理I/O密集型任务。 要在Python实现多线程调用异步,可以使用以下的方式之一: 1. asyncio库:asyncio是Python异步I/O框架,它使用协程来实现异步编程。可以使用asyncio库在多个线程调用异步函数。需要注意的是,在使用asyncio时,应该确保所有的I/O操作都是非阻塞的,否则会阻塞主线程。 2. 多进程 + 异步库:Python也可以通过多进程来实现并行的异步编程。可以使用multiprocessing库来创建多个进程,然后在每个进程使用异步库来处理异步任务。 3. 线程池 + 异步库:Python的concurrent.futures库提供了线程池和进程池的实现,可以通过线程池来实现多线程调用异步。可以使用ThreadPoolExecutor类来创建线程池,并将异步任务提交给线程池处理。 无论采用哪种方式,多线程调用异步都需要注意线程安全和资源共享的问题。需要使用锁和同步机制来保证线程安全,并避免竞态条件和死锁的发生。 综上所述,Python多线程调用异步可以使用asyncio库、多进程和异步库、线程池和异步库等方式实现。具体选择哪种方式取决于实际需求和场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值