0
点赞
收藏
分享

微信扫一扫

Python实现多线程(一)

树下的老石头 2021-09-28 阅读 82

一. 什么是线程

线程也是一种多任务编程的方式,可以使用计算机多核资源。线程又被称为轻量级的进程,线程具有以下特征:

  • 线程是计算机核心分配的最小单位。
  • 一个进程可以包含多个线程。
  • 线程也是一个运行过程,也要消耗计算机资源;多个线程共享其进程的资源和空间。
  • 线程也拥有自己特有的资源属性,比如指令集,TID等。
  • 线程无论创建、删除还是运行,资源消耗都小于进程。
  • 多个线程之间并行执行,互不干扰。

二. 创建线程

Python 中使用 threading 模块创建线程,关于threading模块的常用类/方法的使用总结如下:

import threading
t = threading.Thread(name, target, *agrs, **kwargs)
功能:创建线程对象。
参数:name线程名称;target线程函数;args元组给线程函数传参;kwargs字典给线程函数传参。

t.start()
启动线程。

t.join([timeout])
回收线程。

t.is_alive()
查看线程状态。

t.name
线程名称,默认为 Thread-1。

t.setName()
设置线程名称。

threading.currentThread()
获取当前线程对象。

t.daemon
t.setDaemon(True)
设置守护线程。 默认t.daemon=False,主线程退 出不会影响分支线程;如果设置为True,则主线程退出分支线程也会退出。

  • 主线程退出指的是所有非守护线程运行结束时,主线程才退出。(并不是主线程代码执行完,主线程就会立即退出)。
  • daemon属性的设置在start前。
  • 一般设置daemon后,不会再使用 join。

t.isDaemon()
判断 daemon 属性。

示例代码一 创建Thread的实例,传递一个函数

from threading import Thread,currentThread
from time import sleep
 
def fun_thread(sec,tname):
    '''线程函数,用于修改线程的名称'''
    print("启动线程-->",currentThread().getName(),":",currentThread().is_alive())
    print("setName修改线程名称")
    currentThread().setName(tname)
    sleep(sec)
    print("{}线程结束".format(currentThread().getName()))
 
threads = []  # 维护线程
 
for i in range(3):
    t = Thread(target=fun_thread, name="thread-%d"%i, 
               args=(3,"My"+str(i)+"Thread"))
    threads.append(t)
    t.start()
 
for t in threads:
    t.join()

运行结果:

三. 封装自己的线程类

通过继承Thread类,并运行Thread类中的init方法以获取父类属性,并重写run方法,在线程启动后,将自动执行run方法。

示例代码二 创建Thread的实例,传递一个可调用的类实例

import threading
from time import sleep,ctime
from threading import currentThread
 
loops = [4,2]
 
class ThreadFunc(object):
    def __init__(self, func, args):
        self.func = func
        self.args = args
 
    def __call__(self):
        self.func(*self.args)
 
def loop(nloop, nsec):
    print(ctime(), currentThread().getName(), 'start loop', nloop)
    sleep(nsec)
    print(ctime(), currentThread().getName(), 'end loop', nloop)
 
def main():
    threads = []
    nloops = range(len(loops))
 
    for i in nloops:
        # 由于自定义的类中重写了__call__方法,使得类的实例可以像函数一样被调用
        # 调用时会自动执行__call__这个特殊方法
        t = threading.Thread(target=ThreadFunc(loop, (i, loops[i])))
        threads.append(t)
 
    for i in nloops:
        threads[i].start()
 
    for i in nloops:
        threads[i].join()
 
if __name__ == "__main__":
    main()

运行结果:由于自定义的ThreadFunc类中重写了call方法,使得类的实例可以像函数一样被调用,调用时会自动执行call这个特殊方法。因此可以将类实例赋值给Thread的target参数。

示例代码三 派生Thread的子类,并创建子类的实例

import threading
from time import sleep, ctime
 
loops = (4, 2)
 
class MyThread(threading.Thread):
    def __init__(self, target, args):
        super().__init__()
        self.target = target
        self.args = args
 
    def run(self):
        self.target(*self.args)
 
def loop(nloop, nsec):
    print(ctime(), 'start loop', nloop)
    sleep(nsec)
    print(ctime(), 'end loop', nloop)
 
def main():
    threads = []
    nloops = range(len(loops))
 
    for i in nloops:
        t = MyThread(loop,(i, loops[i]))
        threads.append(t)
 
    for i in nloops:
        threads[i].start()
 
    for i in nloops:
        threads[i].join()
 
if __name__ == "__main__":
    main()
举报

相关推荐

0 条评论