Python快速而美丽[v1.0.0][线程相关类]

线程局部变量

为了解决多线程竞争资源的问题,threading提供了一个local()函数,该函数返回一个线程局部变量,实际上就是为每一个使用该变量的线程都提供一个变量的副本

import threading
from concurrent.futures import ThreadPoolExecutor

# 定义线程局部变量
mydata = threading.local()
# 定义准备作为线程执行体使用的函数
def action (max):
    for i in range(max):
        try:
            mydata.x += i
        except:
            mydata.x = i
        # 访问mydata的x的值
        print('%s mydata.x的值为: %d' % 
            (threading.current_thread().name, mydata.x))
# 使用线程池启动两个子线程
with ThreadPoolExecutor(max_workers=2) as pool:
    pool.submit(action , 10)
    pool.submit(action , 10)

线程局部变量从另一个角度来解决多线程的并发访问问题,但并不能替代同步机制,两者解决的问题不同,同步机制是为了同步多个线程对共享资源的并发访问,是多个线程之间进行通信的有效方式,线程局部变量是为了隔离多个线程的数据共享,从根本上避免多个线程之间对共享资源(变量)的竞争,因此如果多个线程之间需要共享资源,以实现线程通信,则使用同步机制,如果仅仅许愿哦隔离多个线程之间的共享冲突,则使用局部变量

定时器

Thread类提供了一个Timer子类,该子类可用于控制指定函数在特定时间内执行一次

from threading import Timer

def hello():
    print("hello, world")
# 指定10秒后执行hello函数
t = Timer(10.0, hello)
t.start()
from threading import Timer
import time

# 定义总共输出几次的计数器
count = 0
def print_time():
    print("当前时间:%s" % time.ctime())
    global t, count
    count += 1
    # 如果count小于10,开始下一次调度
    if count < 10:
        t = Timer(1, print_time)
        t.start()
# 指定1秒后执行print_time函数
t = Timer(1, print_time)
t.start()

如果程序想取消Timer的调度,则可调用Timer对象的cancel()函数

任务调度

如果要执行更复杂的任务调度,可以使用Python提供的sched模块,该模块提供了sched.schedule类,它就是任务调度器

sched.schedule类构造器

sched.scheduler(timefunc=time.monotonic, delayfunc=time.sleep)构造器接受两个参数

  • timefunc:该参数指定生成时间戳的时间函数,默认使用time.monotonic来生成时间戳
  • dealyfunc:该参数指定阻塞程序的函数,默认调用time.sleep函数来阻塞程序

sched.schedule类函数和属性

  • scheduler.enterabs(time, priority, action, argument=(), kwargs={}):指定在time时间点执行action函数,argument和kwargs都用于向action函数传入参数,其中argument使用位置参数的形式传入参数,kwargs使用关键字参数的形式传入参数;该方法返回一个event,它可作为cancel()方法的参数用于取消调度,priority参数指定该任务的优先级,当在同一个时间点有多个任务需要执行时,优先级高(值越小越高)的任务优先执行
  • scheduler.enter(delay, priority, action, argument=(), kwargs={}):该方法与上一个方法基本相同,只是delay参数用于指定多少秒后执行action任务
  • scheduler.cancel(event):判断当前该调度器的调度队列是否为空
  • scheduler.run(blocking=True):运行所有需要调度的任务,如果调用该方法的blocking参数为Ture,则该方法将会阻塞线程,直到所有被调度的任务都执行完毕
  • scheduler.queue:该只读属性返回该调度器的调度序列

代码示例

import sched, time
import threading

# 定义线程调度器
s = sched.scheduler()

# 定义被调度的函数
def print_time(name='default'):
    print("%s 的时间: %s" % (name, time.ctime()))
print('主线程:', time.ctime())
# 指定10秒之后执行print_time函数
s.enter(10, 1, print_time)
# 指定5秒之后执行print_time函数,优先级为2
s.enter(5, 2, print_time, argument=('位置参数',))
# 指定5秒之后执行print_time函数,优先级为1
s.enter(5, 1, print_time, kwargs={'name': '关键字参数'})
# 执行调度的任务
s.run()
print('主线程:', time.ctime())

执行结果为

C:\Users\davieyang\Downloads\codes\14\14.8>python sched_test.py
主线程: Wed Apr 29 01:22:27 2020
关键字参数 的时间: Wed Apr 29 01:22:32 2020
位置参数 的时间: Wed Apr 29 01:22:32 2020
default 的时间: Wed Apr 29 01:22:37 2020
主线程: Wed Apr 29 01:22:37 2020

猜你喜欢

转载自blog.csdn.net/dawei_yang000000/article/details/105689732