Skip to content

Latest commit

 

History

History
169 lines (118 loc) · 4.53 KB

File metadata and controls

169 lines (118 loc) · 4.53 KB

多线程

一、python线程模块的选择

Python提供了几个用于多线程编程的模块,包括_thread、threading和Queue等。_thread和threading模块允许程序员创建和管理线程。_thread模块提供了基本的线程和锁的支持,threading提供了更高级别、功能更强的线程管理的功能。Queue模块允许用户创建一个可以用于多个线程之间共享数据的队列数据结构。

避免使用_thread模块,因为更高级别的threading模块更为先进,对线程的支持更为完善,而且使用_thread模块里的属性有可能会与threading出现冲突;其次低级别的_thread模块的同步原语很少(实际上只有一个),而threading模块则有很多;再者,_thread模块中当主线程结束时,所有的线程都会被强制结束掉,没有警告也不会有正常的清除工作,至少threading模块能确保重要的子线程退出后进程才退出

_thread模块不支持守护线程,当主线程退出时,所有的子线程不论它们是否还在工作,都会被强行退出。而threading模块支持守护线程,守护线程一般是一个等待客户请求的服务器,如果没有客户提出请求它就在那等着,如果设定一个线程为守护线程,就表示这个线程是不重要的,在进程退出的时候,不用等待这个线程退出。

二、threding模块

  • 导入

    import threading
  • 创建线程

    thr = threading.Thread(target=函数名, args=(参数,) ,name='名字')
    • target 函数名 要执行的任务
    • args 参数 传递给任务的参数
    • name 给线程起名称
  • 设置线程名称

    • 实例化的时候传递name参数
    • thr.setName(名称)
  • 开启线程

    thr.start()

  • 线程等待

    thr.join()

  • 返回当前线程对象

    • threading.current_thread()
    • threading.currentThread()
  • 获取线程名称

    • threading.current_thread().name
    • threading.current_thread().getName()
  • 获取所有线程的名称

    • threading.enumerate()
  • 返回线程是否活动的

    • threading.isAlive()
  • 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

    • threading.activeCount()
  • 实例

    if __name__ == '__main__':
        t1 = Thread(target=task)
        t2 = Thread(target=task)
        t1.start()
        t2.start()
    
        print("查看线程状态,设置线程名,获取线程名","-" * 50)
        print(t1.is_alive())  # 查看是否存在
        print(t2.is_alive())  # 查看是否存在
        t1.setName("子线程一")  # 设置线程1名字
        t2.setName("子线程二")  # 设置线程2名字
        print(t1.getName()) # 获取线程名
        print(t2.getName()) # 获取线程名
    
    
        print("查看当前线程","-" * 50)
        print(currentThread())      # 查看当前线程
        print(currentThread().name)  # 查看当前线程名
        print("查看所有线程","-"*50)
        print(activeCount())    # 查看存活线程个数
        print(enumerate())  # 查看所有线程
        print(len(enumerate())) # 查看所有线程个数

三、开启子线程的两种方式

线程的开启和进程不同,进程是拷贝一份代码去内存中执行。内部调用的是fork创建子进程

而线程是会去执行的指定函数

  1. 通过指定函数的方式
  2. 通过类的继承,实现run方法

方式1:

# 方式一
def task(name):
    print(f'{name} start')
    global x
    x -= 1
    print({name}, x)
    time.sleep(2)
    print(f'{name} end')


if __name__ == '__main__':
    x = 10
    t1 = Thread(target=task,args=("线程1",))
    t2 = Thread(target=task,args=("线程2",))
    t1.start()  # 告诉操作系统开一个线程
    t2.start()  # 告诉操作系统开一个线程

    print('主')

线程1 start {'线程1'} 9 线程2 start {'线程2'} 8 主 线程1 end 线程2 end

3.2、方式2

# 方式二
class Mythread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name

    def run(self):
        print(f'{self.name} start')
        global x
        x -= 1
        print({self.name}, x)
        time.sleep(2)
        print(f'{self.name} end')

if __name__ == '__main__':
    x = 10
    t1 = Mythread("线程1")
    t2 = Mythread("线程2")
    t1.start()
    t2.start()
    print('主')

线程1 start {'线程1'} 9 线程2 start {'线程2'} 8 主 线程1 end 线程2 end

通过上面两组代码你会发现:线程的创建运行比进程快,同一个进程中的线程可以共享资源