线程的实现(Implementation of Threads)
在本章中,我们将学习如何在Python中实现线程。
用于线程实现的Python模块
Python线程有时被称为轻量级进程,因为线程占用的内存比进程少得多。 线程允许一次执行多个任务。 在Python中,我们有以下两个在程序中实现线程的模块 -
《_thread》 module
《threading》 module
这两个模块之间的主要区别在于《_thread》模块将线程视为一个函数,而《threading》模块将每个线程视为一个对象,并以面向对象的方式实现它。 此外, 《_thread》模块在低级线程中是有效的,并且具有比《threading》模块更少的能力。
《_thread》 module
在Python的早期版本中,我们有《thread》模块,但在很长一段时间内它被认为是“已弃用”。 鼓励用户使用《threading》模块。 因此,在Python 3中,模块“thread”不再可用。 它已被重命名为“ 《_thread》 ”以解决《_thread》中的向后不兼容问题。
要在《_thread》模块的帮助下生成新线程,我们需要调用它的start_new_thread方法。 借助以下语法可以理解此方法的工作原理 -
_thread.start_new_thread ( function, args[, kwargs] )
在这里 -
args是一个参数元组
kwargs是关键字参数的可选字典
如果我们想在不传递参数的情况下调用函数,那么我们需要在args使用一个空元组args 。
此方法调用立即返回,子线程启动,并使用传递的args列表(如果有)调用函数。 线程在函数返回时终止。
例子 (Example)
以下是使用《_thread》模块生成新线程的示例。 我们在这里使用start_new_thread()方法。
import _thread
import time
def print_time( threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print ("%s: %s" % ( threadName, time.ctime(time.time()) ))
try:
_thread.start_new_thread( print_time, ("Thread-1", 2, ) )
_thread.start_new_thread( print_time, ("Thread-2", 4, ) )
except:
print ("Error: unable to start thread")
while 1:
pass
输出 (Output)
以下输出将帮助我们在《_thread》模块的帮助下理解新线程的生成。
Thread-1: Mon Apr 23 10:03:33 2018
Thread-2: Mon Apr 23 10:03:35 2018
Thread-1: Mon Apr 23 10:03:35 2018
Thread-1: Mon Apr 23 10:03:37 2018
Thread-2: Mon Apr 23 10:03:39 2018
Thread-1: Mon Apr 23 10:03:39 2018
Thread-1: Mon Apr 23 10:03:41 2018
Thread-2: Mon Apr 23 10:03:43 2018
Thread-2: Mon Apr 23 10:03:47 2018
Thread-2: Mon Apr 23 10:03:51 2018
《threading》 module
《threading》模块以面向对象的方式实现,并将每个线程视为对象。 因此,它为线程提供了比“_thread”模块更强大,更高级的支持。 该模块包含在Python 2.4中。
模块中的其他方法
《threading》模块包含《_thread》模块的所有方法,但它也提供了其他方法。 其他方法如下 -
threading.activeCount() - 此方法返回活动的线程对象的数量
threading.currentThread() - 此方法返回调用者线程控件中的线程对象数。
threading.enumerate() - 此方法返回当前活动的所有线程对象的列表。
run() - run()方法是线程的入口点。
start() - start()方法通过调用run方法启动一个线程。
join([time]) - join()等待线程终止。
isAlive() - isAlive()方法检查线程是否仍在执行。
getName() - getName()方法返回线程的名称。
setName() - setName()方法设置线程的名称。
为了实现线程, 《threading》模块具有Thread类,它提供以下方法 -
如何使用模块创建线程?
在本节中,我们将学习如何使用《threading》模块创建线程。 按照以下步骤使用“线程”模块创建新线程 -
Step 1 - 在这一步中,我们需要定义Thread类的新子类。
Step 2 - 然后,为了添加其他参数,我们需要覆盖__init__(self [,args])方法。
Step 3 - 在这一步中,我们需要覆盖run(self [,args])方法来实现线程在启动时应该做的事情。
现在,在创建新的Thread子类之后,我们可以创建它的一个实例,然后通过调用start()启动一个新线程, start()又调用run()方法。
例子 (Example)
考虑此示例以了解如何使用《threading》模块生成新线程。
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print ("Starting " + self.name)
print_time(self.name, self.counter, 5)
print ("Exiting " + self.name)
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print ("%s: %s" % (threadName, time.ctime(time.time())))
counter -= 1
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("Exiting Main Thread")
Starting Thread-1
Starting Thread-2
输出 (Output)
现在,考虑以下输出 -
Thread-1: Mon Apr 23 10:52:09 2018
Thread-1: Mon Apr 23 10:52:10 2018
Thread-2: Mon Apr 23 10:52:10 2018
Thread-1: Mon Apr 23 10:52:11 2018
Thread-1: Mon Apr 23 10:52:12 2018
Thread-2: Mon Apr 23 10:52:12 2018
Thread-1: Mon Apr 23 10:52:13 2018
Exiting Thread-1
Thread-2: Mon Apr 23 10:52:14 2018
Thread-2: Mon Apr 23 10:52:16 2018
Thread-2: Mon Apr 23 10:52:18 2018
Exiting Thread-2
Exiting Main Thread
各种线程状态的Python程序
有五种线程状态 - 新的,可运行的,运行的,等待的和死的。 在这五个中,我们主要关注三个州 - 跑步,等待和死亡。 线程将其资源置于运行状态,等待处于等待状态的资源; 资源的最终版本,如果执行和获取处于死亡状态。
以下Python程序在start(),sleep()和join()方法的帮助下将分别显示线程如何进入running,waiting和dead状态。
Step 1 - 导入必要的模块,“线程”和“时间”
import threading
import time
Step 2 - 定义一个函数,在创建线程时将调用该函数。
def thread_states():
print("Thread entered in running state")
Step 3 - 我们使用time模块的sleep()方法让我们的线程等待2秒钟。
time.sleep(2)
Step 4 - 现在,我们创建一个名为T1的线程,它接受上面定义的函数的参数。
T1 = threading.Thread(target=thread_states)
Step 5 - 现在,在start()函数的帮助下,我们可以启动我们的线程。 它将生成消息,该消息由我们在定义函数时设置。
T1.start()
Thread entered in running state
Step 6 - 现在,最后我们可以在完成执行后使用join()方法终止线程。
T1.join()
在Python中启动一个线程
在python中,我们可以通过不同的方式启动一个新线程,但其中最简单的一个是将它定义为单个函数。 定义函数后,我们可以将其作为新的threading.Thread对象的目标传递给它。 执行以下Python代码以了解该函数的工作原理 -
import threading
import time
import random
def Thread_execution(i):
print("Execution of Thread {} started\n".format(i))
sleepTime = random.randint(1,4)
time.sleep(sleepTime)
print("Execution of Thread {} finished".format(i))
for i in range(4):
thread = threading.Thread(target=Thread_execution, args=(i,))
thread.start()
print("Active Threads:" , threading.enumerate())
输出 (Output)
Execution of Thread 0 started
Active Threads:
[<_MainThread(MainThread, started 6040)>,
<HistorySavingThread(IPythonHistorySavingThread, started 5968)>,
<Thread(Thread-3576, started 3932)>]
Execution of Thread 1 started
Active Threads:
[<_MainThread(MainThread, started 6040)>,
<HistorySavingThread(IPythonHistorySavingThread, started 5968)>,
<Thread(Thread-3576, started 3932)>,
<Thread(Thread-3577, started 3080)>]
Execution of Thread 2 started
Active Threads:
[<_MainThread(MainThread, started 6040)>,
<HistorySavingThread(IPythonHistorySavingThread, started 5968)>,
<Thread(Thread-3576, started 3932)>,
<Thread(Thread-3577, started 3080)>,
<Thread(Thread-3578, started 2268)>]
Execution of Thread 3 started
Active Threads:
[<_MainThread(MainThread, started 6040)>,
<HistorySavingThread(IPythonHistorySavingThread, started 5968)>,
<Thread(Thread-3576, started 3932)>,
<Thread(Thread-3577, started 3080)>,
<Thread(Thread-3578, started 2268)>,
<Thread(Thread-3579, started 4520)>]
Execution of Thread 0 finished
Execution of Thread 1 finished
Execution of Thread 2 finished
Execution of Thread 3 finished
Python中的守护程序线程
在Python中实现守护程序线程之前,我们需要了解守护程序线程及其用法。 在计算方面,守护进程是一个后台进程,它处理各种服务的请求,例如数据发送,文件传输等。如果不再需要它,它将处于休眠状态。 同样的任务也可以在非守护程序线程的帮助下完成。 但是,在这种情况下,主线程必须手动跟踪非守护程序线程。 另一方面,如果我们使用守护程序线程,那么主线程可以完全忘记这一点,它将在主线程退出时被终止。 关于守护程序线程的另一个重要观点是,我们可以选择仅将它们用于非必要任务,如果它们没有完成或在它们之间被杀死则不会影响我们。 以下是python中守护程序线程的实现 -
import threading
import time
def nondaemonThread():
print("starting my thread")
time.sleep(8)
print("ending my thread")
def daemonThread():
while True:
print("Hello")
time.sleep(2)
if __name__ == '__main__':
nondaemonThread = threading.Thread(target = nondaemonThread)
daemonThread = threading.Thread(target = daemonThread)
daemonThread.setDaemon(True)
daemonThread.start()
nondaemonThread.start()
在上面的代码中,有两个函数,即》nondaemonThread()和》daemonThread() 。 第一个函数打印其状态并在8秒后休眠,而deamonThread()函数每2秒无限期地打印Hello。 我们可以通过以下输出了解nondaemon和daemon线程之间的区别 -
Hello
starting my thread
Hello
Hello
Hello
Hello
ending my thread
Hello
Hello
Hello
Hello
Hello