views:

572

answers:

4

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.

On to my questions:

  1. My main(String[]) block will fire off a separate Superdaemon.
  2. The Superdaemon will poll and loop forever.

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

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

f.get();

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

Regards,

ashitaka

A: 

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).

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.

sblundy
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 ?
ashitaka
+1  A: 

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.

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

Suroot
+6  A: 

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 ?

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).

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.

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).

Thilo
+6  A: 

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.

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.

mtnygard