Python3 多线程(个人总结)

概要:Python中使用多线程主要有_thread和threading两个模块,大多数情况下,只需要使用threading模块即可。

一、线程的创建和调度
通过上一节学习的面向对象知识,只需要继承threading模块的Thread即可,重写构造方法和run方法,使用父类的start()方法启动线程

import threading
import time


class MyThread(threading.Thread):

    def __init__(self, thread_name):
    	# 调用父类构造函数
       	threading.Thread.__init__(self, name=thread_name)

	# 重写run方法
    def run(self):
        print("MyThread:[{}] is running".format(self.name))
        time.sleep(5)
        print("MyThread:[{}] is finshed".format(self.name))


if __name__ == "__main__":
    t1 = time.time()
    for i in range(10):
        myThread = MyThread("Thread{}".format(i))
        myThread.start()
        time.sleep(1)
    t2 = time.time()
    print("All Threads count time:{}".format(t2-t1))

输出结果

F:\Python项目\basic\venv\Scripts\python.exe F:/Python项目/basic/MyThread.py
MyThread:[Thread0] is running
MyThread:[Thread1] is running
MyThread:[Thread2] is running
MyThread:[Thread3] is running
MyThread:[Thread4] is running
MyThread:[Thread0] is finshed
MyThread:[Thread5] is running
MyThread:[Thread1] is finshed
MyThread:[Thread6] is running
MyThread:[Thread2] is finshed
MyThread:[Thread7] is running
MyThread:[Thread3] is finshed
MyThread:[Thread8] is running
MyThread:[Thread4] is finshed
MyThread:[Thread9] is running
MyThread:[Thread5] is finshed
All Threads count time:10.063600063323975
MyThread:[Thread6] is finshed
MyThread:[Thread7] is finshed
MyThread:[Thread8] is finshed
MyThread:[Thread9] is finshed

二、线程同步
多线程中,为了避免线程间资源的相互争抢导致的异常,需要进行锁操作,线程同步可以使用threading模块中的Lock类中提供的方法:acquire和release
示例:

import threading
import time

tickets = 10

class MyThread(threading.Thread):

    def __init__(self, thread_name):
        # 调用父类构造函数
        threading.Thread.__init__(self, name=thread_name)

    # 重写run方法
    def run(self):
        global tickets
        if tickets > 0:
            time.sleep(0.001)
            tickets = tickets - 1
            print("%s 购到票. 票剩余 = %d" % (self.name, tickets))


if __name__ == "__main__":
    i = 0
    while tickets > 0:
        i = i + 1
        thread = MyThread("用户-{}".format(i))
        thread.start()


输出结果:

用户-2 购到票. 票剩余 = 9
用户-1 购到票. 票剩余 = 8
用户-3 购到票. 票剩余 = 7
用户-4 购到票. 票剩余 = 6
用户-5 购到票. 票剩余 = 5
用户-6 购到票. 票剩余 = 4
用户-7 购到票. 票剩余 = 3
用户-9 购到票. 票剩余 = 2
用户-8 购到票. 票剩余 = 1
用户-11 购到票. 票剩余 = 0
用户-10 购到票. 票剩余 = -1
用户-12 购到票. 票剩余 = -2

每次执行结果都随机变化,票超卖了,如果对资源加锁,执行结果将不一样。

import threading
import time

tickets = 10

threadLock = threading.Lock()


class MyThread(threading.Thread):

    def __init__(self, thread_name):
        # 调用父类构造函数
        threading.Thread.__init__(self, name=thread_name)

    # 重写run方法
    def run(self):
        global tickets
        # 获取锁,用于线程同步
        threadLock.acquire()
        if tickets > 0:
            time.sleep(0.001)
            tickets = tickets - 1
            print("%s 购到票. 票剩余 = %d" % (self.name, tickets))
        # 释放锁,开启下一个线程
        threadLock.release()


if __name__ == "__main__":
    i = 0
    while tickets > 0:
        i = i + 1
        thread = MyThread("用户-{}".format(i))
        thread.start()

执行结果:

用户-1 购到票. 票剩余 = 9
用户-2 购到票. 票剩余 = 8
用户-3 购到票. 票剩余 = 7
用户-4 购到票. 票剩余 = 6
用户-5 购到票. 票剩余 = 5
用户-6 购到票. 票剩余 = 4
用户-7 购到票. 票剩余 = 3
用户-8 购到票. 票剩余 = 2
用户-9 购到票. 票剩余 = 1
用户-10 购到票. 票剩余 = 0

三、线程池
线程是宝贵的资源,占用内存,创建和销毁线程需要大量时间,所以并不能无休止的创建新线程,导致内存溢出。Python中线程池可以使用concurrent.futures模块下的ThreadPoolExecutor

  • 构造器:
def __init__(self, max_workers=None, thread_name_prefix='',
                 initializer=None, initargs=()):
  • 示例:
from concurrent.futures import ThreadPoolExecutor
import threading

count = 0


def my_print():
    global count
    count = count + 1
    print("%s is running" % (threading.currentThread().name,))
    return count


def deal_result(c):
	# c.result()取到返回结果
    print("%s :Count is %s" % (threading.currentThread().name, c.result(),))


if __name__ == "__main__":
	# 初始化线程池 max_workers:线程数量, thread_name_prefix:线程名称前缀
    threadPool = ThreadPoolExecutor(max_workers=2, thread_name_prefix='MyThread')
    for i in range(5):
    	# 执行完线程后返回Future对象,通过函数add_done_callback()回调
        threadPool.submit(my_print).add_done_callback(deal_result)
    # 关闭线程池,关闭后不可提交任务
    threadPool.shutdown()
    print("All Task Finshed.")

输出结果:

MyThread_0 is running
MainThread :Count is 1
MyThread_0 is running
MainThread :Count is 2
MyThread_0 is running
MyThread_0 :Count is 3
MyThread_1 is running
MyThread_1 :Count is 4
MyThread_1 is running
MyThread_1 :Count is 5
All Task Finshed.

从结果可以看出,只有线程0和线程1执行任务,主线程(mainThread)执行回调函数

  • 方法说明
class Executor(object):
    """This is an abstract base class for concrete asynchronous executors."""
    def submit(*args, **kwargs):
        """Submits a callable to be executed with the given arguments."""
class Future(object):
"""Represents the result of an asynchronous computation."""
    def add_done_callback(self, fn):
        """Attaches a callable that will be called when the future finishes."""

注:通过给定的参数提交一个可回调的任务,返回对象:<class ‘concurrent.futures._base.Future’>
通过Future对象方法add_done_callback()处理返回结果,参数为回调方法,提交返回结果作为回调方法的入参,通过result()方法获取返回结果的值。

发布了40 篇原创文章 · 获赞 31 · 访问量 62万+

猜你喜欢

转载自blog.csdn.net/weixin_38422258/article/details/104394012
今日推荐