Python实现多线程(一)

一. 什么是线程

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

  • 线程是计算机核心分配的最小单位
  • 一个进程可以包含多个线程
  • 线程也是一个运行过程,也要消耗计算机资源;多个线程共享其进程的资源和空间
  • 线程也拥有自己特有的资源属性,比如指令集,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()

运行结果:

Python实现多线程(一)_第1张图片 

三. 封装自己的线程类

       通过继承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()

 

你可能感兴趣的:(Python处理并发)