Вызовите функцию, не дожидаясь ее

Привет, мне было интересно, есть ли способ вызвать функцию/метод (желательно на Python или Java) и продолжить выполнение, не дожидаясь его.

Пример:

def a():
    b()  #call a function, b()
    return "something"

def b():
    #something that takes a really long time

Ответ 1

Запустите его в новой теме. Узнайте о многопоточности в Java здесь и многопоточности Python здесь

Пример Java:

НЕПРАВИЛЬНЫЙ способ... путем подкласса Thread

new Thread() {
    public void run() {
        YourFunction();//Call your function
    }
}.start();

ПРАВИЛЬНЫЙ способ... путем предоставления Runnable экземпляра

Runnable myrunnable = new Runnable() {
    public void run() {
        YourFunction();//Call your function
    }
}

new Thread(myrunnable).start();//Call it when you need to run the function

Ответ 2

Используя multiprocessing в python:

from multiprocessing import Process

def b():
    # long process

p = Process(target=b) 
p.start()

Ответ 3

Как отмечалось в других ответах, из Python вы можете либо поместить функцию в новый поток (не так уж хорошо, поскольку потоки в CPython вас не очень много) или в другом процессе с использованием Multiprocessing -

from multiprocessing import Process

def b():
    # long process

def a():
    p = Process(target=b) 
    p.start()
    ...
a()

(Как указано в ответе monkut).

Но декоратор Python позволяет скрывать шаблон под ковром, таким образом, что во время вызова вы "видите" только обычный вызов функции. В приведенном ниже примере, Я создаю "параллельный" декоратор - просто поместите его перед любой функцией, и он будет автоматически запускаться в отдельном процессе при вызове:

from multiprocessing import Process
from functools import partial

from time import sleep

def parallel(func):
    def parallel_func(*args, **kw):
        p = Process(target=func, args=args, kwargs=kw)
        p.start()
    return parallel_func

@parallel
def timed_print(x=0):
    for y in range(x, x + 10):
        print y
        sleep(0.2)



def example():
    timed_print(100)
    sleep(0.1)
    timed_print(200)
    for z in range(10):
        print z
        sleep(0.2)


if __name__ == "__main__":
    example()

При запуске этого фрагмента вы получаете:

[[email protected] Documents]$ python parallel.py 
100
0
200
101
1
201
102
2
202
103
3
203
104
4
204
105
5
205
106
6
206
107
7
207
108
8
208
109
9
209
[[email protected] Documents]$ 

Ответ 4

В Java есть стандартная идиома: создайте поток и запустите его:

new Thread() {
    @Override
    public void run() {
        callMyFunction();
    }
}.start();

Или вы можете создать Runnable и передать его в поток:

Runnable caller = new Runnable() {
    @Override
    public void run() {
        callMyFunction();
    }
}

new Thread(caller).start();

Ответ 5

Лучше начинать с ExecutorService вместо того, чтобы идти напрямую с необработанными потоками. Он обеспечивает объединение, завершение обнаружения, и есть подклассы, которые также имеют некоторое планирование. Например:

...
// Create a simple instance with a single thread in the pool
ExecutorService executor = Executors.newFixedThreadPool(1); 
...
Future<Integer> future = executor.submit(new Callable<Integer>() {
    @Override
    public Integer call() {
        return YourFunction();
    }
});
...

// To wait for YourFunction() to finish, and get the result:
Integer result = future.get();

Вы можете отправить столько асинхронных задач в ExecutorService, сколько захотите; они будут выполняться параллельно или последовательно, в зависимости от выбранной вами реализации, от количества потоков в пуле поддерживающих потоков и т.д.

Ответ 6

просто вызовите эту функцию в новом потоке...

Ответ 7

Поскольку jsbueno answer не будет работать во всех системах Windows, так как os.fork не будет работать там эффективно из-за ограничений в ОС, вам придется использовать многопоточность там для достижения того же эффекта.

Пожалуйста, найдите тот же код из ответа jsbueno с многопоточностью вместо многопроцессорности (версия Python 3)

from threading import Thread

from time import sleep

def thread_parallel(func):
    def parallel_func(*args, **kw):
        p = Thread(target=func, args=args, kwargs=kw)
        p.daemon = True
        p.start()
    return parallel_func

@thread_parallel
def timed_print(x=0):
    for y in range(x, x + 10):
        print(y)
        sleep(0.2)


def example():
    timed_print(100)
    sleep(0.1)
    timed_print(200)
    for z in range(10):
        print(z)
        sleep(0.2)


if __name__ == "__main__":
    example()