Dotcpp  >  编程教程  >  Python进程和线程  >  Python如何创建线程

Python如何创建线程

点击打开在线编译器,边学边练

在学习线程的创建之前,我们先来了解一下线程对象线程体这两个概念,线程对象就是我们通过线程模块中的线程类创建的对象,而线程体就是线程执行的相关内容,例如指令和函数等。

线程有四个变化状态:

       1) 创建线程

当创建一个新的进程时,也创建一个新的线程,进程中的线程可以在同一进程中创建新的线程。

       2) 终止线程

可以正常终止自己,也可能某个线程执行错误,由其它线程强行终止。终止线程操作主要负责释放线程占有的寄存器和栈。

       3) 阻塞线程

当线程等待某个事件无法运行时,停止其运行。

       4) 唤醒线程

当阻塞线程的事件发生时,将被阻塞的线程状态置为就绪态,将其挂到就绪队列,进程仍然具有与执行相关的状态。

在Python中有两个系统模块供我们使用:_thread和threading,前者为低级模块,后者对前者进行了封装,通常我们会使用threading模块。

1. threading模块

threading是一种面向对象的模块,其中使用最多的是Thread类,还有几种比较常用的函数:

threading.active_count():返回当前活动的线程数。

threading.current_thread():返回当前的Thread对象。

threading.main_thread():返回主线程对象。

2. Thread类

我们可以使用Thread类来代表一个线程对象,它的语法格式如下:

Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

group应该为None,在实现ThreadGroup类时为将来的扩展保留。

target是run()方法要调用的可调用对象。默认为“无”,表示不调用任何内容。

name是线程名。默认情况下,一个唯一的名称由“Thread-N”构成,其中N是一个小的十进制数。

args是目标调用的参数元组,默认为()。

kwargs是目标调用的关键字参数字典。默认为{}。

我们通过一个例子来看一下,代码如下:

import threading
import time
def test():
    for i in range(2):
        time.sleep(1)#设置一个等待时间
        print('这是第%s线程'%threading.current_thread().name)
if __name__ == '__main__':
    my_list = []
    for i in range(5):
        a = threading.Thread(target=test)
        my_list.append(a)
    for j in my_list:
        j.start()
    for m in my_list:
        m.join()

运行结果为:

这是第Thread-2线程
这是第Thread-1线程
这是第Thread-5线程这是第Thread-4线程
这是第Thread-3线程
这是第Thread-1线程
这是第Thread-2线程
这是第Thread-5线程这是第Thread-4线程这是第Thread-3线程

通过运行结果我们可以看出,线程的执行顺序是不确定的,再加上等待时间,就会出现等待的空白片段,关于这个我们在操作系统中有很多相关内容。

我们主要是通过threading.Thread(target=test)来创建线程,然后把四个线程放在一个列表中,然后我们再通过start()方法开启线程,join()方法等待线程结束。

3. 通过Thread子类创建线程

我们还可以定义一个子类,使这个子类继承Thread线程类中的方法来创建线程,代码如下:

import threading
import time
class MyThread(threading.Thread):
    def __init__(self,name = None):
        super().__init__(name = name)
    def run(self):
        t = threading.current_thread()
        for i in range(4):
            print('第%d次执行线程%s'%(i,t.name))
            time.sleep(1)
        print('执行完毕')
if __name__ == '__main__':
    thread_one = MyThread()
    thread_one.start()
    thread_one.join()
    thread_two = MyThread()
    thread_two.start()

运行结果如下:

第0次执行线程Thread-1第0次执行线程Thread-1
第1次执行线程Thread-1
第2次执行线程Thread-1
第3次执行线程Thread-1
执行完毕
第0次执行线程Thread-2
第1次执行线程Thread-2
第2次执行线程Thread-2
第3次执行线程Thread-2
执行完毕

这种方式等于先定义了一个子类,然后继承了threading.Thread的线程类,然后定义run()方法,然后在主程序中使用我们定义的子类创建两个线程,这两个线程会自动调用run()方法,我们把线程启动然后等待即可。

4. 总结

上面所讲的是我们创建线程的时候最常用的两种方式,通常我们会选择后者去进行创建,在编程的时候给每个线程执行的时间time.sleep(),这样会通过线程暂停而给其它线程来争抢执行的机会,这一点我们在后面会学习到。



本文固定URL:https://www.dotcpp.com/course/299

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Python教程
第一章 Python入门
第二章 Python基础语法
第三章 Python入门语法
第四章 Python核心语法
第五章 Python函数
第六章 Python面向对象编程
第七章 Python模块
第八章 Python异常处理和程序调试
第九章 Python文件及目录操作
第十章 PythonGUI编程
第十一章 Python进程和线程
第十二章 Python数据库管理
第十三章 Python算法
第十四章 Python爬虫
第十五章 Python实战项目
第十六章 后记
Dotcpp在线编译      (登录可减少运行等待时间)