python-进程和线程

目录

1. 并行和并发

2. 进程和线程的概念

3. 线程的状态

4. python中的线程开发

Thread类

线程启动

threading的属性和方法

Thread实例的属性和方法

run方法

在理解进程和线程的概念之前,先了解什么是并行,什么是并发以及并发的解决方案都有哪些?

1. 并行和并发

并行:同一时刻互不干扰的做几件事,例如三个独立的车道分别行驶三辆车

并发:一段时间内处理几件事,例如,多个车辆在某一时段通过同一段路

并发的解决

  • 队列、缓冲区:排队一个一个处理,例如排队上车,队伍就是缓冲区
  • 争抢:锁机制,谁抢到就上排他锁,其余人只能等待。例如:挤公交,只有一个门可以上,谁抢到谁上,后面的人只能等待,弊端为可能有人长时间抢不到
  • 预处理:一种提前加载用户需要的数据的思路,预处理思想,缓存常用。例如,早晚高峰提前调度多辆公交,能够满足现有大部分人的需求
  • 并行:日购买更多服务器,或多开进程、线程实现并行处理,来解决并发问题。注意这些都是水平扩展思想。例如:一次性到多辆公交

    如果线程在单CPU上处理,就不是并行了。但是多数服务器都是多CPU的,服务的部署往往是多机的、分布式的,这都是并行处理
  • 提速:提高单个CPU性能,或单个服务器安装更多的CPU,这是一种垂直扩展思想。例如:将公交核载人数增加
  • 消息中间件:常见的消息中间件有RabbitMQ、ActiveMQ (Apache)、RocketMQ( 阿里Apache)、kafka( Apache)等。

2. 进程和线程的概念

进程:

  • 一个程序的执行实例就是一个进程,表现为程序是源代码编译后的文件,而这些文件存放在磁盘上。当程序被操作系统加载到内存中,就是进程。
  • 进程中存放着指令和数据(资源),它也是线程的容器。
  • 进程( Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
  • Linux进程有父进程、子进程,Windows的进程是平等关系

线程:

  • 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运行单位。
  • 线程,有时被称为轻量级进程(Lightweight Process,LWP),是程序执行流的最小单元。
  • 一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。

进程、线程的理解

  • 进程间不可以随便的共享数据,同一个进程内的线程可以共享进程的资源,每一个线程拥有自己独立的堆栈
  • 在许多系统中,创建一个线程比创建一个进程快10-100倍。

3. 线程的状态

状态 含义
就绪(Ready) 线程能够运行,但在等待被调度。可能线程刚刚创建启动,或刚刚从阻塞中恢复,或者被其他线程抢占
运行(Running) 线程正在运行
阻塞(Blocked) 线程等待外部事件发生而无法运行,如I/0操作
终止(Terminated) 线程完成,或退出,或被取消

     

线程状态的转换

             python-进程和线程_第1张图片

4. python中的线程开发

 进程会启动一个解释器进程,线程共享一个解释器进程

python的线程开发使用标准库threading

Thread类

def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, *, daemon=None):

线程的启动和退出

线程启动

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

python-进程和线程_第2张图片

运行时默认创建一个主线程,start()方法可以创建子线程

示例:

import threading

def add(x, y):
    print("test thread")
    s = x+y
    print(s)
print("主线程")

t1 = threading.Thread(target=add,name='add',args=(4,5))
t2 = threading.Thread(target=add,name='add',kwargs={'x':1,'y':2})

t1.start()
t2.start()

Python没有提供线程退出的方法,线程在下面情况时退出

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

threading的属性和方法

名称 含义
current_thread() 返回当前线程对象
main_thread() 返回主线程对象
active_count() 当前处于alive状态的线程个数
enumerate() 返回所有活着的线程的列表,不包括已经终止的线程和未开始的线程
get_ident() 返回当前线程的ID,非0整数










 

active_count、enumerate方法返回的值还包括主线程

示例:

import threading
import time


def add(x, y):
    s = x+y
    print(s)
    time.sleep(5)
    showthread()
    print("当前线程名称:",threading.currentThread().name)

def showthread():
    print("current_thread:",threading.current_thread())
    print("main_thread:", threading.main_thread())
    print("active_count:", threading.active_count())
    print("thread_id",threading.get_ident())

t1 = threading.Thread(name='add',target=add,args=(4,5))

t1.start()

Thread实例的属性和方法

名称 含义
name 线程名字,名称可以重名。getName()、setName()获取、设置名称
ident

线程ID,它是非0整数。线程启动后才会有ID,否则为None。

线程退出,此ID依旧可以访问。此ID可以重复使用

is_alive() 返回线程是否活着







 

注:线程的name这是一个名称,可以重复;ID必须唯一,但可以在线程退出后再利用

run方法

运行线程函数,不启动新线程,在主线程中执行

import threading

def add(x, y):
    print("test thread")
    s = x+y
    print(s)
print("主线程")

class MyThread(threading.Thread):
    def start(self) -> None:
        print("start")
        super().start()

    def run(self) -> None:
        print("run")
        super().run()

t1 = MyThread(target=add,name='add',args=(4,5))
t2 = threading.Thread(target=add,name='add',kwargs={'x':1,'y':2})

t1.start()
t2.run()

start()和run() 方法的区别

  • start()方法会调用run()方法,而run()方法可以运行函数
  • 使用start方法启动线程,启动了一个新的线程。
  • 使用run方法,并没有启动新的线程,就是在主线程中调用了一个普通的函数而已。

因此,启动线程请使用start方法,才能启动多个线程。

你可能感兴趣的:(Python,开发语言,python)