添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

线程有四个变化状态:

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(),这样会通过线程暂停而给其它线程来争抢执行的机会,这一点我们在后面会学习到。


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

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

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

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

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

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

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

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

C++派生类的析构函数实例详解

Socket编程之WSAStartup函数

C语言指针的定义和使用

Linux reboot命令:重新启动计算机

理解复杂度概念

C语言格式化输入函数scanf实例详解

C语言setjmp()函数:非局部转移进程

Ubuntu安装nginx图文教程

C语言实现五子棋游戏教程及代码

Java标识符与关键字

四种基本的编程命名规范

少儿编程和成年编程有什么区别

C语言中^是平方吗?

C语言如何更改窗口大小

代码该怎么优化?

原码与源码的区别

什么是函数指针

编程命名规范之驼峰式命名法

机器数与机器码的区别

常用的元字符及其在正则表达式中的写法

第二章 Python基础语法 第三章 Python入门语法 第四章 Python核心语法 第五章 Python函数 第六章 Python面向对象编程 第七章 Python模块 第八章 Python异常处理和程序调试 第九章 Python文件及目录操作 第十章 PythonGUI编程 第十一章 Python进程和线程 第十二章 Python数据库管理 第十三章 Python算法 第十四章 Python爬虫 第十五章 Python实战项目 第十六章 后记