Расписание Python, повторяющее несколько потоков

Ну, моя проблема заключается в следующем. У меня есть сценарий, в котором я хочу запустить 3 функции, каждая из которых в различном интервале. Все трое делятся ресурсом. Я сделал следующее (где res - общий ресурс):

import threading
import thread

lock = threading.Lock()

def f1(res) :
  lock.acquire()
  # do stuff
  time = 10.0 # this one changes each time f1 runs
  lock.release()
  threading.Timer(time,f1).start()

def f2(res) :
  lock.acquire()
  # do stuff
  time = 8.0 # this one changes each time f2 runs
  lock.release()
  threading.Timer(time,f2).start()

def f3(res) :
  lock.acquire()
  # do stuff
  time = 8.0 # this one changes each time f3 runs
  lock.release()
  threading.Timer(time,f3).start()

thread.start_new_thread(f1(res))
thread.start_new_thread(f2(res))
thread.start_new_thread(f3(res))

Когда я выполняю код, происходит то, что только первый поток (f1) выполняется вечно и фактически без ожидания времени, установленного в таймере. Может ли кто-нибудь помочь, объяснив мне, что я делаю неправильно и как я могу исправить это?

Заранее спасибо.

2 ответа

Решение

Когда я выполняю код, происходит то, что только первый поток (f1) выполняется вечно и фактически без ожидания времени, установленного в таймере.

Похоже, что первый поток запущен, он порождает новый поток таймера, и должно быть join там, что не позволяет исходному потоку завершиться, пока не завершится его подпоток. Поскольку этот подпоток порождает подпоток и т. Д., Исходный поток никогда не заканчивается.

Тот факт, что выполняется только f1, может быть потому, что в этой строке

thread.start_new_thread(f1(res))

внутренний аргумент f1(res) оценивается до того, как его возвращаемое значение передается thread.start_new_thread, Итак, вы на самом деле звоните f1(res) сначала из основного потока, не порождая поток для вызова f1,

Нет необходимости использовать thread Модуль здесь. Вы можете делать все, что вам нужно, с высокоуровневым интерфейсом, предоставляемым threading модуль. Кроме того, линия

 thread.start_new_thread(f1(res))

поднимает

TypeError: start_new_thread expected at least 2 arguments, got 1

так что я не уверен, как вы получили свой код для запуска...

Вот альтернативный способ сделать то, что (я думаю) вы хотите.

import threading
import logging
logger = logging.getLogger(__name__)
lock = threading.Lock()

def f1():
    with lock:
        logger.info('f1')
        threading.Timer(10, f1).start()

def f2():
    with lock:
        logger.info('f2')
        threading.Timer(8, f2).start()

def f3():
    with lock:
        logger.info('f3')
        threading.Timer(23, f3).start()

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG,
                        format='[%(asctime)s %(threadName)s] %(message)s',
                        datefmt='%H:%M:%S')
    threading.Thread(target=f1).start()
    threading.Thread(target=f2).start()
    threading.Thread(target=f3).start()

который печатает что-то вроде:

[10:53:12 Thread-1] f1
[10:53:12 Thread-3] f2
[10:53:12 Thread-4] f3
[10:53:20 Thread-5] f2
[10:53:22 Thread-2] f1
[10:53:28 Thread-7] f2
[10:53:32 Thread-8] f1
[10:53:35 Thread-6] f3
[10:53:36 Thread-9] f2
  C-c C-\Quit

Отметка времени показывает, что f1 запускается каждые 10 секунд, f2 каждые 8 ​​секунд и f3 каждые 23 секунды.

Код ниже работает для меня. Вы уверены, что #do stuff в f1 не виновник?

import threading
import thread

lock = threading.Lock()

def f1(res) :
    lock.acquire()
    print "F1"
    lock.release()
    threading.Timer(1.0,f1, [res]).start()

def f2(res) :
    lock.acquire()
    print "F2"
    lock.release()
    threading.Timer(2.0,f2, [res]).start()

def f3(res) :
    lock.acquire()
    print "F3"
    lock.release()
    threading.Timer(3.0,f3, [res]).start()

thread.start_new_thread(f1, (res,))
thread.start_new_thread(f2, (res,))
thread.start_new_thread(f3, (res,))
Другие вопросы по тегам