Python的线程Thread的自我介绍

简介: Python的线程Thread的自我介绍

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: 为目标函数关键字传参, 字典.(同上,只不过是字典类型的)

640.png


运行结果:


640.png

通过threading.Thread创建一个线程对象,target是目标函数,name可以指定名称.

但是,仅仅生成线程对象是不行的,我们还需要启动它,这个时候就需要调用start方法,如上图第七行代码所示。


线程会执行函数(def function():.....),是因为线程中就是执行代码的,而最简单的封装就是函数,所以还是函数调用.函数执行完,线程也会随之退出.下面我们看一个一直执行的例子:

640.png

我们把刚刚的运行函数变成了一个死循环,所以他会一直不停的运行下去。

结果:

640.png


刚刚在运行第一个例子的时候我们看到了,当run_thread函数运行结束的时候,我们的线程也结束了,所以说,线程结束的标准就是,当它需要执行的东西执行完毕了,它就自然而然的结束了,但是也有例外,如果说,线程执行的函数抛出了异常呢,线程还会继续执行下去吗?

我们来看看例子:

还是将上面的run_thread函数修改一下:

640.png

看一下运行结果:

640.png

ok,看了上面的运行结果我们就知道答案是否定的,一旦线程内的方法抛出异常,那么它本身将不会再执行了。所以我们总结一下,一般线程在什么时候会退出:

  • 线程函数内语句执行完毕.
  • 线程函数中抛出未处理的异常.

在python中,线程不具有优先级或线程组的概念,也不能被销毁、停止、挂起,自然也没有恢复、中断。这一点和其他语言是不一样的。



下面我们讲一下线程的属性和方法:

current_thread()  # 返回当前线程对象.

main_thread()  # 返回主线程对象.

active_count()  # 当前处于alive状态的线程个数.

enumerate()  # 返回所有活着的线程的列表

get_ident()  # 返回当前线程ID,非0整数.

start()  # 启动线程。每一个线程必须且只能执行该方法一次。

run()  # 运行线程函数。

写个代码看看他们是什么吧:

640.jpg

执行结果:


640.png


我们现在来看一下run方法是什么方法,怎么现在都没用过?

其实我们已经在用了,我们之前用的start()方法会调用run()方法,run()方法可以运行函数。


640.png

我们写一个自己的类继承自threading,我们重写了start方法和run方法,并且在里面加了标记,现在我们来跑一下代码:

640.png

结果打印出来了”调用了run方法“,这就证明了我们刚刚的说法是对的





下面我们看看多线程,多线程是什么呢?当然就是许多许多线程同时在一起工作啦!

很简单,我们可以给刚刚的函数生成多个线程对象不久可以了吗?(是不是很聪明,哈哈哈哈)

640.jpg

看输出结果:

640.png

正好是执行四次(他们的顺序是无序的,我把t1-t4这样写出来是为了证明有四个线程,他们之间运行没有先后,就看谁先抢到资源,谁就先运行了)

当使用start方法启动线程后,进程内有多个活动的线程并行的工作,就是多线程。

一个进程中至少有一个线程,并作为程序的入口,这个线程就是主线程。一个进程至少有一个主线程。其他线程称为工作线程。



在多线程的时候我们经常会用到join方法,join方法是控制一个线程调用另一个线程的方法。join方法有一点是要强调的,就是它是保证当前线程运行完成后再去执行其他线程的。

我们来看一个简单的例子:

首先我们不用join:

640.png


它会直接把结果一下子就输出来,程序结束,不会一秒一秒的等。

如果我们把join加上,hello world!就会一秒一秒地有序输出,然后结束程序。


join有一个timeout参数:

  1. 当设置守护线程时,含义是主线程对于子线程等待timeout的时间将会杀死该子线程,最后退出程序。所以说,如果有10个子线程,全部的等待时间就是每个timeout的累加和。简单的来说,就是给每个子线程一个timeout的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死。

  2. 没有设置守护线程时,主线程将会等待timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。



关于线程,我们今天就介绍到这里啦!

相关文章
|
3月前
|
安全 数据处理 开发者
Python中的多线程编程:从入门到精通
本文将深入探讨Python中的多线程编程,包括其基本原理、应用场景、实现方法以及常见问题和解决方案。通过本文的学习,读者将对Python多线程编程有一个全面的认识,能够在实际项目中灵活运用。
|
2月前
|
Java C# Python
线程等待(Thread Sleep)
线程等待是多线程编程中的一种同步机制,通过暂停当前线程的执行,让出CPU时间给其他线程。常用于需要程序暂停或等待其他线程完成操作的场景。不同语言中实现方式各异,如Java的`Thread.sleep(1000)`、C#的`Thread.Sleep(1000)`和Python的`time.sleep(1)`。使用时需注意避免死锁,并考虑其对程序响应性的影响。
|
16天前
|
Java 程序员 调度
【JavaEE】线程创建和终止,Thread类方法,变量捕获(7000字长文)
创建线程的五种方式,Thread常见方法(守护进程.setDaemon() ,isAlive),start和run方法的区别,如何提前终止一个线程,标志位,isinterrupted,变量捕获
|
16天前
|
安全 Java API
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程
|
2月前
|
数据采集 存储 数据处理
Python中的多线程编程及其在数据处理中的应用
本文深入探讨了Python中多线程编程的概念、原理和实现方法,并详细介绍了其在数据处理领域的应用。通过对比单线程与多线程的性能差异,展示了多线程编程在提升程序运行效率方面的显著优势。文章还提供了实际案例,帮助读者更好地理解和掌握多线程编程技术。
|
2月前
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
2月前
|
Java Unix 调度
python多线程!
本文介绍了线程的基本概念、多线程技术、线程的创建与管理、线程间的通信与同步机制,以及线程池和队列模块的使用。文章详细讲解了如何使用 `_thread` 和 `threading` 模块创建和管理线程,介绍了线程锁 `Lock` 的作用和使用方法,解决了多线程环境下的数据共享问题。此外,还介绍了 `Timer` 定时器和 `ThreadPoolExecutor` 线程池的使用,最后通过一个具体的案例展示了如何使用多线程爬取电影票房数据。文章还对比了进程和线程的优缺点,并讨论了计算密集型和IO密集型任务的适用场景。
123 4
|
3月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
47 3
|
3月前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
73 2
|
3月前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
47 2