Python 多线程教程|Python 主题月

本文正在参加「Python主题月」,详情查看 活动连接python

在这个 Python 多线程教程中,您将看到建立线程的不一样方法,并学习实现线程安全操做的同步。这篇文章的每一个部分都包含一个示例和示例代码,以逐步解释该概念。git

顺便说一下,多线程是几乎全部高级编程语言都支持的软件编程的核心概念。所以,您应该知道的第一件事是:什么是线程以及多线程在计算机科学中意味着什么。github

什么是计算机科学中的线程?

在软件编程中,线程是具备独立指令集的最小执行单元。它是进程的一部分,并在共享程序的可运行资源(如内存)的相同上下文中运行。一个线程有一个起点、一个执行顺序和一个结果。它有一个指令指针,用于保存线程的当前状态并控制接下来按什么顺序执行。面试

什么是计算机科学中的多线程?

一个进程并行执行多个线程的能力称为多线程。理想状况下,多线程能够显着提升任何程序的性能。并且 Python 多线程机制很是人性化,您能够快速学习。编程

多线程的优势

  • 多线程能够显着提升多处理器或多核系统的计算速度,由于每一个处理器或核同时处理一个单独的线程。
  • 多线程容许程序在一个线程等待输入时保持响应,同时另外一个线程运行 GUI。此陈述适用于多处理器或单处理器系统。
  • 进程的全部线程均可以访问其全局变量。若是一个全局变量在一个线程中发生变化,那么它对其余线程也是可见的。线程也能够有本身的局部变量。

多线程的缺点

  • 在单处理器系统上,多线程不会影响计算速度。因为管理线程的开销,性能可能会降低。
  • 访问共享资源时须要同步以防止互斥。它直接致使更多的内存和 CPU 利用率。
  • 多线程增长了程序的复杂性,从而也使得调试变得困难。
  • 它增长了潜在死锁的可能性。
  • 当线程没法按期访问共享资源时,它可能会致使饥饿。应用程序将没法恢复其工做。

到目前为止,您已经阅读了有关线程的理论概念。若是您不熟悉 Python,咱们建议您阅读咱们的 30 个快速 Python 编码技巧,它们也能够帮助您编写 Python 多线程代码。咱们的许多读者都使用了这些技巧,而且可以提升他们的编码技能。安全

Python 多线程模块

Python 提供了两个模块来在程序中实现线程。markdown

  • ** **模块和
  • **<线程> **模块。

注意:供您参考,Python 2.x 曾经有 < thread> 模块。但它在 Python 3.x 中被弃用并重命名为 <  _thread> 模块以实现向后兼容性。数据结构

两个模块的主要区别在于模块<_线程>将线程实现为函数。另外一方面,< threading >模块提供了一种面向对象的方法来启用线程建立。多线程

如何使用线程模块建立线程?

若是你决定在你的程序中应用< thread > 模块,那么使用下面的方法来产生线程。app

#语法

thread.start_new_thread ( function, args[, kwargs] )
复制代码

这种方法对于建立线程很是有效和直接。您可使用它在 Linux 和 Windows 中运行程序。

此方法启动一个新线程并返回其标识符。它将使用传递的参数列表调用指定为“函数”参数的函数。当 < function > 返回时,线程将静默退出。

这里,args是一个参数元组;使用空元组调用 < function > 不带任何参数。可选的 < kwargs > 参数指定关键字参数的字典。

**若是 < function > 因未处理的异常而终止,则会打印堆栈跟踪,而后线程退出(它不会影响其余线程,它们会继续运行)。使用如下代码了解有关线程的更多信息。

基本的 Python 多线程示例

#Python 多线程示例。
#1. 使用递归计算阶乘。
#2. 使用线程调用阶乘函数。

from _thread import start_new_thread
from time import sleep

threadId = 1 #线程计数器
waiting = 2 #2秒等待的时间

def factorial(n):
    global threadId
    rc = 0
    
    if n < 1:   # base case
        print("{}: {}".format('\nThread', threadId ))
        threadId += 1
        rc = 1
    else:
        returnNumber = n * factorial( n - 1 )  # recursive call
        print("{} != {}".format(str(n), str(returnNumber)))
        rc = returnNumber
    
    return rc

start_new_thread(factorial, (5, ))
start_new_thread(factorial, (4, ))

print("Waiting for threads to return...")
sleep(waiting)
复制代码

您能够在本地 Python 终端中运行上述代码,也可使用任何在线 Python 终端。执行此程序后,它将产生如下输出。

程序输出

# Python 多线程:程序输出-
等待线程返回...

Thread: 1
1 != 1
2 != 2
3 != 6
4 != 24
5 != 120

Thread: 2
1 != 1
2 != 2
3 != 6
4 != 24
复制代码

如何使用线程模块建立线程?

最新的< threading >模块比上一节讨论的遗留< thread >模块提供了丰富的特性和更好的线程支持。< threading > 模块是 Python 多线程的一个很好的例子。

threading > 模块结合了 < thread > 模块的全部方法,并暴露了一些额外的方法

  • threading.activeCount(): 它找到总数。活动线程对象。
  • threading.currentThread(): 您可使用它来肯定调用方线程控制中的线程对象数量。
  • threading.enumerate(): 它将为您提供当前活动的线程对象的完整列表。

除了上述方法,< threading >模块还提供了< Thread >类,你能够尝试实现线程。它是 Python 多线程的面向对象的变体。

Thread > 类发布如下方法。

类方法 方法说明
run(): 它是任何线程的入口点函数。
start(): start() 方法在 run 方法被调用时触发一个线程。
join([time]): join() 方法使程序可以等待线程终止。
isAlive(): isAlive() 方法验证活动线程。
getName(): getName() 方法检索线程的名称。
setName(): setName() 方法更新线程的名称。

使用线程模块实现线程的步骤

您能够按照如下步骤使用 < threading > 模块实现一个新线程。

  • 从 < Thread > 类构造一个子类。
  • 覆盖 <  init(self [,args])  > 方法以根据要求提供参数。
  • 接下来,重写< run(self [,args])  > 方法来编写线程的业务逻辑。

一旦定义了新的 < Thread> 子类,就必须实例化它以启动一个新线程。而后,调用 < start()> 方法来启动它。它最终会调用< run()> 方法来执行业务逻辑。

示例 – 建立一个线程类来打印日期

#Python 多线程示例打印当前日期。
#1. 使用 threading.Thread 类定义子类。
#2. 实例化子类并触发线程。

import threading
import datetime

class myThread (threading.Thread):
    def __init__(self, name, counter):
        threading.Thread.__init__(self)
        self.threadID = counter
        self.name = name
        self.counter = counter
    def run(self):
        print("\nStarting " + self.name)
        print_date(self.name, self.counter)
        print("Exiting " + self.name)

def print_date(threadName, counter):
    datefields = []
    today = datetime.date.today()
    datefields.append(today)
    print("{}[{}]: {}".format( threadName, counter, datefields[0] ))

# 建立新线程
thread1 = myThread("Thread", 1)
thread2 = myThread("Thread", 2)

# 启动新线程
thread1.start()
thread2.start()

thread1.join()
thread2.join()
print("\nExiting the Program!!!")
复制代码

程序输出

Starting Thread
Thread[1]: 2021-07-22
Exiting Thread

Starting Thread
Thread[2]: 2021-07-22
Exiting Thread

Exiting the Program!!!
复制代码

Python 多线程——同步线程

threading > 模块具备实现锁定的内置功能,容许您同步线程。须要锁定来控制对共享资源的访问,以防止损坏或丢失数据。

您能够调用 Lock() 方法来应用锁,它返回新的锁对象。而后,您能够调用锁对象的获取(阻塞) 方法来强制线程同步运行。

可选的阻塞参数指定线程是否等待获取锁。

  • Case Blocking = 0:若是获取锁失败,线程将当即返回零值,若是锁成功则返回一。
  • Case Blocking = 1:线程阻塞并等待锁被释放。

锁对象的release() 方法用于在再也不须要时释放锁。

仅供参考,Python 的内置数据结构(例如列表、字典)是线程安全的,由于它具备用于操做它们的原子字节码的反作用。在 Python 中实现的其余数据结构或基本类型(如整数和浮点数)没有这种保护。为了防止同时访问一个对象,咱们使用了一个Lock 对象。

锁定的多线程示例

#Python 多线程示例来演示锁定。
#1. 使用 threading.Thread 类定义子类。
#2. 实例化子类并触发线程。
#3. 在线程的 run 方法中实现锁。

import threading
import datetime

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, name, counter):
        threading.Thread.__init__(self)
        self.threadID = counter
        self.name = name
        self.counter = counter
    def run(self):
        print("\nStarting " + self.name)
        # 获取锁同步线程
        threadLock.acquire()
        print_date(self.name, self.counter)
        # 为下一个线程释放锁
        threadLock.release()
        print("Exiting " + self.name)

def print_date(threadName, counter):
    datefields = []
    today = datetime.date.today()
    datefields.append(today)
    print("{}[{}]: {}".format( threadName, counter, datefields[0] ))

threadLock = threading.Lock()
threads = []

# 建立新线程
thread1 = myThread("Thread", 1)
thread2 = myThread("Thread", 2)

# 启动新线程
thread1.start()
thread2.start()

# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)

# 等待全部线程完成
for thread in threads:
    thread.join()

print("\nExiting the Program!!!")
复制代码

程序输出

Starting Thread
Thread[1]: 2021-07-22
Exiting Thread

Starting Thread
Thread[2]: 2021-07-22
Exiting Thread

Exiting the Program!!!
复制代码

总结——初学者的 Python 多线程

我但愿您会发现这个 Python 多线程教程很是有趣且引人入胜。若是您喜欢这篇文章并有兴趣看到更多此类文章,能够看看这里(Github/Gitee) 关注我以查看更多信息,这里汇总了个人所有原创及做品源码

🧵 更多相关文章

往日优秀文章推荐:

若是你真的从这篇文章中学到了一些新东西,喜欢它,收藏它并与你的小伙伴分享。🤗最后,不要忘了❤或📑支持一下哦

相关文章
相关标签/搜索