Hello,我是Python里面的线程,今天我就来向大家做个自我介绍吧!
首先,我想说的是,我(线程)不只是在python中会出现,我在任何编程语言中都可以使用代码将我实现,所以,简单来说我是一个机制,在一些特别的情况下会遇到我。
在我自我介绍之前,我先要介绍我的组织——进程( 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.)
进程呢,是容纳我的地方,一个进程可以容纳包含许多许多的线程
关于组织(进程)和我(线程)之间的关系如下:
A 在实现了线程的操作系统中,线程是操作系统能够运算调度的最小单位.
(我是最小单位,组织里面有多个我,我是不能被拆分的)
B 线程被包含在进程中,是进程的实际运作单位.
(我隶属于组织,组织是以一个我为单位,由好多很多个我组成的)
C 一个程序的执行实例就是一个进程.
(关于组织其实很好理解,一个组织就是一个完整程序)
介绍完我和进程的关系后,现在我开始来自我介绍啦!
首先要和大家介绍一下我的四个形态:
Ready:就是一开始在准备的状态,一旦我运行了,就在等着被组织调度呢。
Running:这个状态下,我正在被组织派出去执行任务呢。
Blocked:这个时候我就很难受了,由于接收到组织的指令,让我停止当前任务,处于待命状态,进又不是,退又不是,不能动,很难受啊。
Terminated:终结状态,此时的我回到组织休息了,无论我的任务是完成了还是被取消了,我都回到组织准备休假了。
搞清楚这些之后我们就来看看在python中的我是什么样子吧!
在python中,我的名字就是:threading模块
如果想使用我,就需要:
import threading
或者直接引入模块中的方法:
from threading import thread
我们先来看看开发者是怎么定义我的吧:
def
__init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None)
在构造函数中,我包含以下几个参数:
* target: 线程调用的对象,就是目标函数.(必须要写)
* name: 为线程起个名字.(必须要写)
* args: 为目标函数传递实参, 元组.(有需要传入线程参数的时候才会用)
* kwargs: 为目标函数关键字传参, 字典.(同上,只不过是字典类型的)
运行结果:
通过threading.Thread创建一个线程对象,target是目标函数,name可以指定名称.
但是,仅仅生成线程对象是不行的,我们还需要启动它,这个时候就需要调用start方法,如上图第七行代码所示。
线程会执行函数(def function():.....),是因为线程中就是执行代码的,而最简单的封装就是函数,所以还是函数调用.函数执行完,线程也会随之退出.下面我们看一个一直执行的例子:
我们把刚刚的运行函数变成了一个死循环,所以他会一直不停的运行下去。
结果:
刚刚在运行第一个例子的时候我们看到了,当run_thread函数运行结束的时候,我们的线程也结束了,所以说,线程结束的标准就是,当它需要执行的东西执行完毕了,它就自然而然的结束了,但是也有例外,如果说,线程执行的函数抛出了异常呢,线程还会继续执行下去吗?
我们来看看例子:
还是将上面的run_thread函数修改一下:
看一下运行结果:
ok,看了上面的运行结果我们就知道答案是否定的,一旦线程内的方法抛出异常,那么它本身将不会再执行了。所以我们总结一下,一般线程在什么时候会退出:
在python中,线程不具有优先级或线程组的概念,也不能被销毁、停止、挂起,自然也没有恢复、中断。这一点和其他语言是不一样的。
下面我们讲一下线程的属性和方法:
current_thread() # 返回当前线程对象.
main_thread() # 返回主线程对象.
active_count() # 当前处于alive状态的线程个数.
enumerate() # 返回所有活着的线程的列表
get_ident() # 返回当前线程ID,非0整数.
start() # 启动线程。每一个线程必须且只能执行该方法一次。
run() # 运行线程函数。
写个代码看看他们是什么吧:
执行结果:
我们现在来看一下run方法是什么方法,怎么现在都没用过?
其实我们已经在用了,我们之前用的start()方法会调用run()方法,run()方法可以运行函数。
我们写一个自己的类继承自threading,我们重写了start方法和run方法,并且在里面加了标记,现在我们来跑一下代码:
结果打印出来了”调用了run方法“,这就证明了我们刚刚的说法是对的
下面我们看看多线程,多线程是什么呢?当然就是许多许多线程同时在一起工作啦!
很简单,我们可以给刚刚的函数生成多个线程对象不久可以了吗?(是不是很聪明,哈哈哈哈)
看输出结果:
正好是执行四次(他们的顺序是无序的,我把t1-t4这样写出来是为了证明有四个线程,他们之间运行没有先后,就看谁先抢到资源,谁就先运行了)
当使用start方法启动线程后,进程内有多个活动的线程并行的工作,就是多线程。
一个进程中至少有一个线程,并作为程序的入口,这个线程就是主线程。一个进程至少有一个主线程。其他线程称为工作线程。
在多线程的时候我们经常会用到join方法,join方法是控制一个线程调用另一个线程的方法。join方法有一点是要强调的,就是它是保证当前线程运行完成后再去执行其他线程的。
我们来看一个简单的例子:
首先我们不用join:
它会直接把结果一下子就输出来,程序结束,不会一秒一秒的等。
如果我们把join加上,hello world!就会一秒一秒地有序输出,然后结束程序。
join有一个timeout参数:
关于线程,我们今天就介绍到这里啦!