python 线程并发
在本章中,我们将学习如何在python中实现线程。
用于线程实现的python模块
python线程有时被称为轻量级进程,因为线程占用的内存比进程少得多。线程允许一次执行多个任务。在python中,我们有以下两个在程序中实现线程的模块
<_thread>
模块模块
这两个模块之间的主要区别在于 模块将线程视为一个函数,而
模块将每个线程视为一个对象,并以面向对象的方式实现它。此外,
< _thread>
模块在低级线程中是有效的,并且具有比< threading>模块更少的功能。
<_thread>
模块
在早期版本的python中,我们使用了 模块,但很长一段时间它被认为是“已弃用”。鼓励用户改为使用
模块。因此,在python 3中,模块
thread
不再可用。它已被重命名为 <_thread>
,以便在python3中向后兼容。
要在 <_thread>
模块的帮助下生成新线程,我们需要调用它的 start_new_thread
方法。借助以下语法可以理解此方法的工作原理
_thread.start_new_thread ( function, args[, kwargs] )
在这里
- args 是一个参数元组
- kwargs 是关键字参数的可选字典
如果我们想在不传递参数的情况下调用函数,那么我们需要在 args
中 使用一个空元组 参数 。
此方法调用立即返回,子线程启动,并使用传递的args列表(如果有)调用函数。线程在函数返回时终止。
例
以下是使用 <_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
输出
以下输出将帮助我们在 <_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
模块
所述 模块实现在面向对象的方式并设为每个线程作为对象。因此,它为线程提供了比
<_thread>
模块更强大,更高级的支持。该模块包含在python2.4中。
模块中的其他方法
所述 模块包括的所有方法
<_thread>
模块,但它提供了额外的方法为好。其他方法如下 -
threading.activecount()
- 此方法返回活动的线程对象的数量threading.currentthread()
- 此方法返回调用者线程控件中的线程对象数。threading.enumerate()
- 此方法返回当前活动的所有线程对象的列表。
为了实现线程, 模块有 thread 类,它提供以下方法
* run() \- run()方法是线程的入口点。
* start() \- start()方法通过调用run方法启动一个线程。
* join([time]) \- join()等待线程终止。
* isalive() \- isalive()方法检查线程是否仍在执行。
* getname() \- getname()方法返回线程的名称。
* setname() \- setname()方法设置线程的名称。
如何使用
模块创建线程?
在本节中,我们将学习如何使用 模块创建线程。按照以下步骤使用模块创建新线程
- 第1步 - 在这一步中,我们需要定义
thread
类的新子类。 - 第2步 - 然后,为了添加其他参数,我们需要覆盖
__init __(self [,args])
方法。 - 第3步 - 在这一步中,我们需要覆盖
run(self [,args])
方法来实现线程在启动时应该做的事情。
现在,在创建新的 thread 子类之后,我们可以创建它的一个实例,然后通过调用 start() 启动一个新线程, start() 又调用 run() 方法。
例
考虑此示例以了解如何使用 模块生成新线程。
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
输出
现在,考虑以下输出
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
状态。
步骤1 - 导入必要的模块, 和
import threading import time
第2步 - 定义一个函数,在创建线程时将调用该函数。
def thread_states(): print("thread entered in running state")
第3步 - 我们使用time模块的sleep()方法让我们的线程等待2秒钟。
time.sleep(2)
第4步 - 现在,我们创建一个名为t1的线程,它接受上面定义的函数的参数。
t1 = threading.thread(target=thread_states)
第5步 - 现在,在start()
函数的帮助下,我们可以启动我们的线程。 它将生成消息,该消息由我们在定义函数时设置。
t1.start() thread entered in running state
第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())
输出
execution of thread 0 started active threads: [<_mainthread(mainthread, started 6040)>, , ] execution of thread 1 started active threads: [<_mainthread(mainthread, started 6040)>, , , ] execution of thread 2 started active threads: [<_mainthread(mainthread, started 6040)>, , , , ] execution of thread 3 started active threads: [<_mainthread(mainthread, started 6040)>, , , , , ] 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