请稍候,加载中....

threading多线程模块

from threading import Thread

Thread属性

属性 描述
name 线程名
ident 线程标识符
daemon 布尔标志,是否为守护线程

Thread方法

__init__(

    ['self', 'group=None', 'target=None', 'name=None', 'args=()', 'kwargs=None', '*', 'daemon=None'],

)

实例化一个线程对象
target:可调用的函数或者方法
args:传递给target的参数,数据类型是可迭代对象
kwargs: 关键字参数
daemon: daemon标志

start() 开始执行线程
run() 定义线程功能的方法(通常在子类中被应用开发者重写)
join(timeout=None) 直至启动的线程终止前一直挂起,除非给出timeout,否则一直阻塞
is_alive() isAlive()已经放弃,返回一个布尔值,表示当前线程是否已经存活,True为存活
isDaemon() 返回一个布尔值,如果为True,表示是守护线程
setDaemon(daemonic) 设置self.daemon为daemonic布尔值

 

创建Thread实例举例

from time import sleep
from random import randint

def myfun(i):
    sleep(randint(1,3))
    print("线程编号:",i)

for i in range(1,5):
    t = Thread(target=myfun, args=(i,))
    t.start()

print("主线程运行结束")

运行结果:

# 主线程运行结束

# 线程编号: 1
# 线程编号: 4
# 线程编号: 2
# 线程编号: 3

注意看输出结果,线程编号由于加入了随时sleep,所以输出顺序是不一定的, 另外所有输出是在"主线程运行结束"后输出。

所有的线程对象创建后,并不会立即执行,而是需要t.start()之后才会执行

使用join强制等待子线程运行结束

for i in range(1,5): 
    t = Thread(target=myfun, args=(i,))
    t.start()
    # 在  t.start() 之后
    # 添加上一行
    t.start()
    t.join()

运行结果

# 线程编号: 1
# 线程编号: 2
# 线程编号: 3
# 线程编号: 4
# 主线程运行结束

加入join后,必须等待线程结束才能开始执行一个新的线程,主线程会阻塞到子线程执行完毕后

Thread子类实现

Thread子类需要重写run方法

class MyThread(Thread):
    def __init__(self, func, args, name=''):
        super().__init__()
        self.name = name
        self.func = func
        self.args = args

    def get_results(self):
        return self.res

    # 子类必须实现方法
    def run(self):
        self.res = self.func(*self.args)


def func1(arg1, arg2):
    return arg1 * arg

def func2(arg1, arg2):
    return arg1 ** arg2

t1 = MyThread(func1, (3,4), "")
t1.start()
t2 = MyThread(func2, (3,4), "")
t2.start()
# 输出线程执行结果
print(t1.get_results())
print(t2.get_results())

 

 


线程锁

锁有两种状态:锁定与未锁定,锁的方法也只有两个:获得锁,释放锁

锁的工作流程:

  1. 多个线程争夺一个锁
  2. 获得锁的线程进入执行
  3. 执行完毕,释放锁
  4. 重复以上步骤

导入Lock对象

from threading import Lock

实例Lock对象

lock = Lock()

lock实例方法

方法名 说明
acquire() 请求锁
release() 释放锁

不加锁示例

from time import sleep

data = []
def myfun(i):
    global data
    data.append(i)
    sleep(randint(1,5))
    data.append(i*10)

t_list = []
for i in range (1,10):
    t = Thread(target=myfun, args=(i,))
    t.start()
    t_list.append(t)

for t in t_list:
    t.join()

print(data)

输出结果

# [1, 2, 3, 4, 5, 6, 7, 8, 9, 60, 40, 70, 30, 80, 10, 50, 20, 90]

加锁示例

data = []
t_list = []

def myfun(i):
    global data
    lock.acquire()
    data.append(i)
    sleep(randint(1,5))
    data.append(i*10)
    lock.release()


for i in range (1,10):
    t = Thread(target=myfun, args=(i,))
    t.start()
    t_list.append(t)

for t in t_list:
    t.join()

print(data)

加锁后的输出

# [1, 10, 2, 20, 3, 30, 4, 40, 5, 50, 6, 60, 7, 70, 8, 80, 9, 90]

预防死锁

如果在锁释放之前,线程退出,就会造成死锁,所以务必对这种情况进行处理

使用异常语句

# try:
#   lock.acquire()
#   ...
# finally:
#   lock.release()

使用with语句

# with lock:
#     ...

 

threading实用函数

函数名 说明
active_count() 返回当前的活动线程数量
current_thread() 返回对应于调用者的控制线程的Thread对象
enumerate() 列出所有活动的Thread对象
local() 返回local对象,用于保存线程的本地数据
setprofile(func) 设置一个配置文件函数,用于创建所有的线程,func在每个线程开始运行之前被传递给sys.setprofile()函数
settrace(func) 设置一个跟踪函数,用于已创建的所有线程,func在每个线程开始运行之前,被传递给sys.settrace()
stack_size([size]) 返回创建新线程使用的栈大小。可选的参数size指定创建线程时使用的大小,为4KB的倍数

 


Python学习手册-