【问题标题】:Call a function without waiting for it无需等待即可调用函数
【发布时间】:2012-07-12 21:20:33
【问题描述】:

您好,我想知道是否有一种方法可以调用函数/方法(最好在 Python 或 Java 中)并继续执行而无需等待。

例子:

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

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

【问题讨论】:

  • 检查 stackoverflow.com/questions/395704/threads-in-python 以获得在 Python 中使用线程的教程链接
  • 顺便说一句,引用无需等待结果即可运行的方法的简单方法是“异步”。可能有助于在您的研究中了解这一点。

标签: java python function methods


【解决方案1】:

在新线程中运行它。了解java中的多线程here和python多线程here

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

【讨论】:

  • 请不要鼓励任何人直接将 Thread 子类化,这几乎没有必要(如果是这样的话,这个人会在没有 SO 帮助的情况下知道他们在做什么),这是不好的做法,并且可能导致一些令人惊讶的错误。
  • 我冒昧地注释了答案......因为这很重要。
  • @StephenC 感谢您的编辑,但是为什么子类化线程是错误的?
  • @Ashwin 一方面,runnable 通常不是通用线程(没有人愿意将它用作通用线程),但真正的问题是你的类突然继承了你的几个方法可能没有想到,基类可能会做一些令人惊讶的事情。例如线程使用实例的对象作为锁并等待它——所以如果你有一个同步方法,那可能会导致一些意外。
【解决方案2】:

由于 jsbueno 的答案不适用于所有 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()

【讨论】:

    【解决方案3】:

    您最好从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 提交任意数量的异步任务;它们将并行或顺序执行,具体取决于您选择的实现、支持线程池中的线程数等。

    【讨论】:

      【解决方案4】:

      正如其他答案中所述,从 Python 中,您可以将函数放在新线程中(不是那么好,因为 CPython 中的线程不会为您带来太多好处),或者在另一个使用 Multiprocessing 的进程中 -

      from multiprocessing import Process
      
      def b():
          # long process
      
      def a():
          p = Process(target=b) 
          p.start()
          ...
      a()
      

      (正如蒙库特的回答)。

      但是 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()
      

      运行这个 sn-p 时,会得到:

      [gwidion@caylus 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
      [gwidion@caylus Documents]$ 
      

      【讨论】:

        【解决方案5】:

        在python中使用multiprocessing

        from multiprocessing import Process
        
        def b():
            # long process
        
        p = Process(target=b) 
        p.start()
        

        【讨论】:

          【解决方案6】:

          在 Java 中,有一个标准的习惯用法:创建一个线程并运行它:

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

          或者您可以创建一个 Runnable 并将其传递给线程:

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

          【讨论】:

          • 您的第一个选项是在后台运行,无需等待即可执行?
          • @Arvindraja - 是的。这两个选项的行为相同。
          猜你喜欢
          • 2020-04-18
          • 1970-01-01
          • 1970-01-01
          • 2015-08-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-02
          • 2015-02-19
          相关资源
          最近更新 更多