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

时间:2022-06-17 21:01:38

I want to write a command line daemon that runs forever. I understand that if I want the JVM to be able to shutdown gracefully in linux, one needs to wrap the bootstrap via some C code. I think I'll be ok with a shutdown hook for now.

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

On to my questions:

关于我的问题:

  1. My main(String[]) block will fire off a separate Superdaemon.
  2. 我的主(String [])块将触发一个单独的Superdaemon。

  3. The Superdaemon will poll and loop forever.
  4. Superdaemon将永远轮询和循环。

So normally I would do:

通常我会这样做:

class Superdaemon extends Thread { ... }

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

        t.join();
    }
}

Now I figured that if I started Superdaemon via an Executor, I can do

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

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

f.get();

Is Future.get() implemented with Thread.join() ? If not, does it behave equivalently ?

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

Regards,

ashitaka

4 个解决方案

#1


Yes, the way you've written these is equivalent.

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

However, you don't really need to wait for the Superdaemon thread to complete. When the main thread finishes executing main(), that thread exits, but the JVM will not. The JVM will keep running until the last non-daemon thread exits its run method.

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

For example,

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");
  }
}

You'll see the output:

你会看到输出:

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

In other words, the main thread finishes first, then the secondary thread completes and the JVM exits.

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

#2


The issue is that books like JCIP is advocating that we use Executors to starts Threads. So I'm trying my best not to use Thread.start(). I'm not sure if I would necessarily choose a particular way of doing things just based on simplicity. There must be a more convincing reason, no ?

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

The convincing reason to use java.util.concurrent is that multi-threaded programming is very tricky. Java offers the tools to that (Threads, the synchronized and volatile keywords), but that does not mean that you can safely use them directly without shooting yourself in the foot: Either too much synchronization, resulting in unnecessary bottlenecks and deadlocks, or too less, resulting in erratic behaviour due to race conditions).

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

With java.util.concurrent you get a set of utilities (written by experts) for the most common usage patterns, that you can just use without worrying that you got the low-level stuff right.

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

In your particular case, though, I do not quite see why you need a separate Thread at all, you might as well use the main one:

但是,在您的特定情况下,我不太明白为什么您需要一个单独的线程,您可能也使用主要的:

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

Executors are meant for tasks that you want to run in the background (when you have multiple parallel tasks or when your current thread can continue to do something else).

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

#3


Future.get() will get the future response from an asynchronous call. This will also block if the call has not been completed yet. It is much like a thread join.

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

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

#4


Sort'a. Future.get() is for having a thread go off and calculate something and then return it to the calling thread in a safe fashion. It'd work if the get never returned. But, I'd stick with the join call as it's simpler and no Executer overhead (not that there would be all that much).

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

Edit

It looks like ExecutorService.submit(Runnable) is intended to do exectly what you're attempting. It just returns null when the Runnable completes. Interesting.

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

#1


Yes, the way you've written these is equivalent.

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

However, you don't really need to wait for the Superdaemon thread to complete. When the main thread finishes executing main(), that thread exits, but the JVM will not. The JVM will keep running until the last non-daemon thread exits its run method.

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

For example,

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");
  }
}

You'll see the output:

你会看到输出:

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

In other words, the main thread finishes first, then the secondary thread completes and the JVM exits.

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

#2


The issue is that books like JCIP is advocating that we use Executors to starts Threads. So I'm trying my best not to use Thread.start(). I'm not sure if I would necessarily choose a particular way of doing things just based on simplicity. There must be a more convincing reason, no ?

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

The convincing reason to use java.util.concurrent is that multi-threaded programming is very tricky. Java offers the tools to that (Threads, the synchronized and volatile keywords), but that does not mean that you can safely use them directly without shooting yourself in the foot: Either too much synchronization, resulting in unnecessary bottlenecks and deadlocks, or too less, resulting in erratic behaviour due to race conditions).

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

With java.util.concurrent you get a set of utilities (written by experts) for the most common usage patterns, that you can just use without worrying that you got the low-level stuff right.

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

In your particular case, though, I do not quite see why you need a separate Thread at all, you might as well use the main one:

但是,在您的特定情况下,我不太明白为什么您需要一个单独的线程,您可能也使用主要的:

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

Executors are meant for tasks that you want to run in the background (when you have multiple parallel tasks or when your current thread can continue to do something else).

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

#3


Future.get() will get the future response from an asynchronous call. This will also block if the call has not been completed yet. It is much like a thread join.

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

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

#4


Sort'a. Future.get() is for having a thread go off and calculate something and then return it to the calling thread in a safe fashion. It'd work if the get never returned. But, I'd stick with the join call as it's simpler and no Executer overhead (not that there would be all that much).

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

Edit

It looks like ExecutorService.submit(Runnable) is intended to do exectly what you're attempting. It just returns null when the Runnable completes. Interesting.

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