Future.get()是Thread.join()的替代品吗?

时间:2009-03-06 03:15:34

标签: java concurrency

我想编写一个永远运行的命令行守护程​​序。我知道如果我希望JVM能够在linux中正常关闭,那么需要通过一些C代码来包装引导程序。我想我现在可以使用关机钩了。

关于我的问题:

  1. 我的主(String [])块将触发一个单独的Superdaemon。
  2. Superdaemon将永远轮询和循环。
  3. 通常我会这样做:

    class Superdaemon extends Thread { ... }
    
    class Bootstrap
    {
        public static void main( String[] args )
        {
            Thread t = new Superdaemon();
            t.start();
    
            t.join();
        }
    }
    

    现在我想,如果我通过Executor启动Superdaemon,我可以做到

    Future<?> f = exec.submit( new Superdaemon() );
    
    f.get();
    

    使用Thread.join()实现Future.get()吗? 如果不是,它的行为是否相同?

    此致

    足高

4 个答案:

答案 0 :(得分:12)

是的,你写这些的方式是等价的。

但是,您并不需要等待Superdaemon线程完成。当主线程完成执行main()时,该线程退出,但JVM不会。 JVM将一直运行,直到最后一个非守护程序线程退出其run方法。

例如,

public class KeepRunning {
  public static void main(String[] args) {
    Superdaemon d = new Superdaemon();
    d.start();
    System.out.println(Thread.currentThread().getName() + ": leaving main()");
  }
}

class Superdaemon extends Thread {
  public void run() {
    System.out.println(Thread.currentThread().getName() + ": starting");
    try { Thread.sleep(2000); } catch(InterruptedException e) {}
    System.out.println(Thread.currentThread().getName() + ": completing");
  }
}

你会看到输出:

main: leaving main()
Thread-0: starting
Thread-0: completing

换句话说,主线程首先完成,然后辅助线程完成,JVM退出。

答案 1 :(得分:6)

  

问题是像JCIP这样的书籍主张我们使用Executors来启动Threads。所以我尽量不要使用Thread.start()。我不确定我是否一定会选择一种基于简单性的特定方式。必须有一个更令人信服的理由,不是吗?

使用 java.util.concurrent 的令人信服的理由是多线程编程非常棘手。 Java提供了相应的工具(Threads, synchronized volatile 关键字),但这并不意味着您可以直接安全地使用它们而不会让自己陷入脚下:太多的同步,导致不必要的瓶颈和死锁,或者太少,导致由于竞争条件导致的不稳定行为)。

使用 java.util.concurrent ,您可以获得一组实用程序(由专家编写),用于最常见的使用模式,您可以使用它而不必担心您的低级别内容正确

在你的特殊情况下,我不太明白为什么你需要一个单独的线程,你也可以使用主要的:

public static void main( String[] args )
{
    Runnable t = new Superdaemon();
    t.run();
}

执行程序适用于您希望在后台运行的任务(当您有多个并行任务或当前线程可以继续执行其他操作时)。

答案 2 :(得分:1)

Future.get()将从异步调用获得未来的响应。如果呼叫尚未完成,这也将阻止。这很像一个线程连接。

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Future.html

答案 3 :(得分:0)

Sort'a。 Future.get()用于让一个线程关闭并计算一些东西,然后以安全的方式将它返回给调用线程。如果get从未返回,它就会起作用。但是,我坚持使用join调用,因为它更简单,并且没有Executer开销(并不会有那么多)。

修改

看起来ExecutorService.submit(Runnable)旨在表现出您正在尝试的内容。它只是在null完成时返回Runnable。有趣。