title: ExecutorService vs Casual Thread Spawner
body: <p>I have a basic question about how <code>ExecutorService</code> works in Java.</p>
  
  <p>It is quite hard to see the difference between simply creating <code>Threads</code> to perform some tasks in parallel and assigning each tasks to the <code>ThreadPool</code>.</p>
  
  <p>The <code>ExecutorService</code> also looks very simple and efficient to use, so I was wondering why we don't use it all the time. </p>
  
  <p>Is it just a matter of one way executing its job faster than the other ?</p>
  
  <p>Here's two very simple examples to show the difference between the two ways :</p>
  
  <p><strong>Using executor service: Hello World (task)</strong> </p>
  
  <pre><code>static class HelloTask implements Runnable {
      String msg;
  
      public HelloTask(String msg) {
          this.msg = msg; 
      }
      public void run() {
          long id = Thread.currentThread().getId();
          System.out.println(msg + " from thread:" + id);
      }
  }
  </code></pre>
  
  <p><strong>Using executor service: Hello World (creating executor, submitting)</strong></p>
  
  <pre><code>static class HelloTask {
      public static void main(String[] args) {
          int ntasks = 1000;
          ExecutorService exs = Executors.newFixedThreadPool(4);
  
          for (int i=0; i&lt;ntasks; i++) { 
              HelloTask t = new HelloTask("Hello from task " + i);    
              exs.submit(t);
          }
          exs.shutdown();
      }
  }
  </code></pre>
  
  <hr>
  
  <p>the following shows a similar example but extending the Callable interface, could you tell me the difference between the two and in which cases one should use a specific one instead of the other ?</p>
  
  <p><strong>Using executor service: Counter (task)</strong></p>
  
  <pre><code>static class HelloTaskRet implements Callable&lt;Long&gt; {
      String msg;
  
      public HelloTaskRet(String msg) {
          this.msg = msg; }
  
          public Long call() {
          long tid = Thread.currentThread().getId(); 
          System.out.println(msg + " from thread:" + tid); 
          return tid;
      } 
  }
  </code></pre>
  
  <p><strong>Using executor service:  (creating, submitting)</strong>    </p>
  
  <pre><code>static class HelloTaskRet {
      public static void main(String[] args) {
          int ntasks = 1000;
          ExecutorService exs = Executors.newFixedThreadPool(4);
  
          Future&lt;Long&gt;[] futures = (Future&lt;Long&gt;[]) new Future[ntasks];
  
          for (int i=0; i&lt;ntasks; i++) { 
              HelloTaskRet t = new HelloTaskRet("Hello from task " + i);
              futures[i] = exs.submit(t);
          }
          exs.shutdown();
      }
  }
  </code></pre>