Я хочу выполнять задачи асинхронно и одновременно. Если task1
работает, когда приходит task2
, task2
запускается сразу, без ожидания завершения task2
. Также я хотел бы избежать обратных вызовов с помощью сопрограмм.
Вот параллельное решение с обратными вызовами:
def fibonacci(n):
if n <= 1:
return 1
return fibonacci(n - 1) + fibonacci(n - 2)
class FibonacciCalculatorFuture:
def __init__(self):
self.pool = ThreadPoolExecutor(max_workers=2)
@staticmethod
def calculate(n):
print(f"started n={n}")
return fibonacci(n)
def run(self, n):
future = self.pool.submit(self.calculate, n)
future.add_done_callback(lambda f: print(f.result()))
if __name__ == '__main__':
calculator = FibonacciCalculatorFuture()
calculator.run(35)
calculator.run(32)
print("initial thread can continue its work")
Его выход:
started n=35
started n=32
initial thread can continue its work
3524578
14930352
А вот мое усилие избавиться от обратных вызовов:
class FibonacciCalculatorAsync:
def __init__(self):
self.pool = ThreadPoolExecutor(max_workers=2)
self.loop = asyncio.get_event_loop()
@staticmethod
def calculate_sync(n):
print(f"started n={n}")
return fibonacci(n)
async def calculate(self, n):
result = await self.loop.run_in_executor(self.pool, self.calculate_sync, n)
print(result)
def run(self, n):
asyncio.ensure_future(self.calculate(n))
if __name__ == '__main__':
calculator = FibonacciCalculatorAsync()
calculator.run(35)
calculator.run(32)
calculator.loop.run_forever()
print("initial thread can continue its work")
Выход:
started n=35
started n=32
3524578
14930352
В этом случае начальный поток не сможет идти дальше, чем loop.run_forever()
и, следовательно, не сможет принимать новые задачи.
Итак, вот мой вопрос : есть ли способ одновременно:
- выполнять задачи одновременно;
- иметь возможность принимать новые задачи и планировать их выполнение сразу же (вместе с уже запущенными тактами);
- использовать сопрограммы и код без обратных вызовов.