两次触发并行运行的2个线程

问题描述 投票:1回答:1

我的代码。它从内部调度程序开始2个线程,这些调度程序每秒打印一次数字

import threading
import time
from datetime import datetime

import schedule

_lock = threading.Lock()


def p(number):
    _lock.acquire()
    print(number, datetime.now())
    _lock.release()


def f(number):
    schedule.every(5).seconds.do(p, number)
    while True:
        schedule.run_pending()
        time.sleep(1)


thread = threading.Thread(target=f, args=(1,))
thread2 = threading.Thread(target=f, args=(2,))
thread.start()
thread2.start()

预期输出

1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:22.821887
2 2020-03-25 22:07:22.821887
1 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093

实际输出(请参阅在17'处代替4个打印件,在27'处代替2个打印件)

1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:22.821887
2 2020-03-25 22:07:22.821887
1 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093

我实际上不知道为什么有时线程触发器的功能不止一次。知道我做错了什么吗?

python python-multithreading schedule
1个回答
1
投票

[两个线程都将任务添加到schedule,并且两个线程都执行run_pending()。这里可能发生的情况是,一个线程执行run_pending()导致两个计划任务都运行,但是在run_pending()在第一个线程中完成执行(并将未完成的任务标记为已完成)之前,第二个线程进入并同时执行run_pending(),从而使所有待处理的任务执行两次。

通过从函数p中移出锁并将其置于run_pending()周围,我无法复制两次被触发任务的行为。

def f(number):
    schedule.every(5).seconds.do(p, number)
    while True:
        _lock.acquire()
        schedule.run_pending()
        _lock.release()
        time.sleep(1)

请注意,您也可以重写程序,以便只有一个线程调用run_pending(),如下所示:

import threading
import time
from datetime import datetime

import schedule

def p(number):
    print(number, datetime.now())

schedule.every(5).seconds.do(p, 1)
schedule.every(5).seconds.do(p, 2)

def task_runner():
    while True:
        schedule.run_pending()
        time.sleep(1)

thread = threading.Thread(target=task_runner)
thread.start()

这是假设您要使用主线程执行除计划任务以外的其他任务。或者,您可以只在应用程序的事件循环中调用run_pending(),而无需在单独的线程中进行调用。

© www.soinside.com 2019 - 2024. All rights reserved.