Name all the threads.
Initialize build log FileHandler once per process.
diff --git a/src/com/facebook/buck/android/BUCK b/src/com/facebook/buck/android/BUCK
index 7be1768..9fb3aca 100644
--- a/src/com/facebook/buck/android/BUCK
+++ b/src/com/facebook/buck/android/BUCK
@@ -140,6 +140,7 @@
     '//src/com/facebook/buck/util:exceptions',
     '//src/com/facebook/buck/util:io',
     '//src/com/facebook/buck/util:util',
+    '//src/com/facebook/buck/util/concurrent:concurrent',
     '//src/com/facebook/buck/util/environment:environment',
     '//src/com/facebook/buck/zip:steps',
     '//src/com/facebook/buck/zip:stream',
diff --git a/src/com/facebook/buck/android/SmartDexingStep.java b/src/com/facebook/buck/android/SmartDexingStep.java
index f329a2f..82187c9 100644
--- a/src/com/facebook/buck/android/SmartDexingStep.java
+++ b/src/com/facebook/buck/android/SmartDexingStep.java
@@ -48,7 +48,6 @@
 import com.google.common.hash.Hashing;
 import com.google.common.io.Files;
 import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
 
 import java.io.File;
 import java.io.IOException;
@@ -56,10 +55,12 @@
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.Executors;
 
 import javax.annotation.Nullable;
 
+import static com.facebook.buck.util.concurrent.MoreExecutors.newMultiThreadExecutor;
+import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
+
 /**
  * Optimized dx command runner which can invoke multiple dx commands in parallel and also avoid
  * doing unnecessary dx invocations in the first place.
@@ -124,7 +125,7 @@
     } else {
       numThreadsValue = determineOptimalThreadCount();
     }
-    return MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(numThreadsValue));
+    return listeningDecorator(newMultiThreadExecutor(getClass().getSimpleName(), numThreadsValue));
   }
 
   private final ListeningExecutorService getDxExecutor() {
diff --git a/src/com/facebook/buck/cli/AdbCommandRunner.java b/src/com/facebook/buck/cli/AdbCommandRunner.java
index c532198..fdc03b4 100644
--- a/src/com/facebook/buck/cli/AdbCommandRunner.java
+++ b/src/com/facebook/buck/cli/AdbCommandRunner.java
@@ -26,15 +26,16 @@
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
 
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
 
 import javax.annotation.Nullable;
 
+import static com.facebook.buck.util.concurrent.MoreExecutors.newMultiThreadExecutor;
+import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
+
 /**
  * Base class for commands that use the AndroidDebugBridge to run commands on devices.
  * Currently, {@link InstallCommand}, {@link UninstallCommand}.
@@ -220,9 +221,8 @@
 
     // Start executions on all matching devices.
     List<ListenableFuture<Boolean>> futures = Lists.newArrayList();
-    ListeningExecutorService executorService = MoreExecutors.listeningDecorator(
-        Executors.newFixedThreadPool(adbThreadCount));
-
+    ListeningExecutorService executorService =
+        listeningDecorator(newMultiThreadExecutor(getClass().getSimpleName(), adbThreadCount));
     for (final IDevice device : devices) {
       futures.add(executorService.submit(adbCallable.forDevice(device)));
     }
diff --git a/src/com/facebook/buck/cli/BUCK b/src/com/facebook/buck/cli/BUCK
index 74081e7..1addbfa 100644
--- a/src/com/facebook/buck/cli/BUCK
+++ b/src/com/facebook/buck/cli/BUCK
@@ -58,6 +58,7 @@
     '//src/com/facebook/buck/util:network',
     '//src/com/facebook/buck/util:util',
     '//src/com/facebook/buck/util/unit:unit',
+    '//src/com/facebook/buck/util/concurrent:concurrent',
     '//src/com/facebook/buck/util/environment:environment',
     '//src/com/facebook/buck/timing:timing',
     '//third-party/java/astyanax:astyanax-cassandra',
diff --git a/src/com/facebook/buck/cli/BuildCommandOptions.java b/src/com/facebook/buck/cli/BuildCommandOptions.java
index ee9b29d..7875a0e 100644
--- a/src/com/facebook/buck/cli/BuildCommandOptions.java
+++ b/src/com/facebook/buck/cli/BuildCommandOptions.java
@@ -34,14 +34,14 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
 
 import org.kohsuke.args4j.Argument;
 import org.kohsuke.args4j.Option;
 
 import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
+
+import static com.facebook.buck.util.concurrent.MoreExecutors.newMultiThreadExecutor;
+import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
 
 public class BuildCommandOptions extends AbstractCommandOptions {
 
@@ -130,8 +130,7 @@
   }
 
   public ListeningExecutorService createListeningExecutorService() {
-    ExecutorService executorService = Executors.newFixedThreadPool(numThreads);
-    return MoreExecutors.listeningDecorator(executorService);
+    return listeningDecorator(newMultiThreadExecutor(getClass().getSimpleName(), numThreads));
   }
 
   Build createBuild(BuckConfig buckConfig,
diff --git a/src/com/facebook/buck/cli/Main.java b/src/com/facebook/buck/cli/Main.java
index 970fca4..f39b8ad 100644
--- a/src/com/facebook/buck/cli/Main.java
+++ b/src/com/facebook/buck/cli/Main.java
@@ -140,6 +140,7 @@
       fileEventBus.register(parser);
       fileEventBus.register(hashCache);
       webServer = createWebServer(config, console);
+      JavaUtilsLoggingBuildListener.ensureLogFileIsWritten();
     }
 
     private Optional<WebServer> createWebServer(BuckConfig config, Console console) {
@@ -346,12 +347,15 @@
     // Create or get and invalidate cached command parameters.
     Parser parser;
     if (context.isPresent()) {
+      // Wire up daemon to new client and console and get cached Parser.
       Daemon daemon = getDaemon(projectFilesystem, config, console);
       daemon.watchClient(context.get());
       daemon.watchFileSystem(console);
-      daemon.initWebServer();
+      daemon.initWebServer(); // TODO(user): avoid webserver initialization on each command?
       parser = daemon.getParser();
     } else {
+      // Initialize logging and create new Parser for new process.
+      JavaUtilsLoggingBuildListener.ensureLogFileIsWritten();
       parser = new Parser(projectFilesystem,
           knownBuildRuleTypes,
           console,
@@ -529,8 +533,6 @@
       buckEvents.register(eventListener);
     }
 
-    JavaUtilsLoggingBuildListener.ensureLogFileIsWritten();
-
     return eventListeners;
   }
 
diff --git a/src/com/facebook/buck/cli/QueryCommand.java b/src/com/facebook/buck/cli/QueryCommand.java
index 3e9d283..04a7aa6 100644
--- a/src/com/facebook/buck/cli/QueryCommand.java
+++ b/src/com/facebook/buck/cli/QueryCommand.java
@@ -24,6 +24,7 @@
 import com.facebook.buck.rules.DependencyGraph;
 import com.facebook.buck.util.BuckConstant;
 import com.facebook.buck.util.HumanReadableException;
+import com.facebook.buck.util.Threads;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Joiner;
@@ -272,12 +273,14 @@
    * @param graphDb database service to shut down.
    */
   private static void registerShutdownHook(final GraphDatabaseService graphDb) {
-    Runtime.getRuntime().addShutdownHook(new Thread() {
-      @Override
-      public void run() {
-        graphDb.shutdown();
-      }
-    });
+    Runtime.getRuntime().addShutdownHook(Threads.namedThread(
+        QueryCommand.class.getSimpleName(),
+        new Runnable() {
+          @Override
+          public void run() {
+            graphDb.shutdown();
+          }
+        }));
   }
 
   private void clearDbPath() {
diff --git a/src/com/facebook/buck/event/BuckEventBus.java b/src/com/facebook/buck/event/BuckEventBus.java
index 4727dbc..35c810b 100644
--- a/src/com/facebook/buck/event/BuckEventBus.java
+++ b/src/com/facebook/buck/event/BuckEventBus.java
@@ -44,7 +44,7 @@
 
 
   public BuckEventBus(Clock clock, String buildId) {
-    this(clock, MoreExecutors.newSingleThreadExecutor(), buildId);
+    this(clock, MoreExecutors.newSingleThreadExecutor(BuckEventBus.class.getSimpleName()), buildId);
   }
 
   @VisibleForTesting
diff --git a/src/com/facebook/buck/event/listener/SuperConsoleEventBusListener.java b/src/com/facebook/buck/event/listener/SuperConsoleEventBusListener.java
index 350607f..615fca7 100644
--- a/src/com/facebook/buck/event/listener/SuperConsoleEventBusListener.java
+++ b/src/com/facebook/buck/event/listener/SuperConsoleEventBusListener.java
@@ -32,6 +32,7 @@
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.eventbus.Subscribe;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
 
 import java.util.Comparator;
 import java.util.Map;
@@ -77,7 +78,8 @@
 
     this.logEvents = new ConcurrentLinkedQueue<>();
 
-    this.renderScheduler = Executors.newScheduledThreadPool(1);
+    this.renderScheduler = Executors.newScheduledThreadPool(1,
+        new ThreadFactoryBuilder().setNameFormat(getClass().getSimpleName() + "-%d").build());
     this.testFormatter = new TestResultFormatter(console.getAnsi());
   }
 
diff --git a/src/com/facebook/buck/json/ProjectBuildFileParser.java b/src/com/facebook/buck/json/ProjectBuildFileParser.java
index f87b5bb..c1f40b4 100644
--- a/src/com/facebook/buck/json/ProjectBuildFileParser.java
+++ b/src/com/facebook/buck/json/ProjectBuildFileParser.java
@@ -19,6 +19,7 @@
 import com.facebook.buck.util.Ansi;
 import com.facebook.buck.util.InputStreamConsumer;
 import com.facebook.buck.util.ProjectFilesystem;
+import com.facebook.buck.util.Threads;
 import com.facebook.buck.util.environment.Platform;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Charsets;
@@ -124,9 +125,11 @@
     OutputStream stdin = buckPyProcess.getOutputStream();
     InputStream stderr = buckPyProcess.getErrorStream();
 
-    Thread stderrConsumer = new Thread(new InputStreamConsumer(stderr,
-        System.err,
-        new Ansi(Platform.detect())));
+    Thread stderrConsumer = Threads.namedThread(
+        ProjectBuildFileParser.class.getSimpleName(),
+        new InputStreamConsumer(stderr,
+            System.err,
+            new Ansi(Platform.detect())));
     stderrConsumer.start();
 
     buckPyStdinWriter = new BufferedWriter(new OutputStreamWriter(stdin));
diff --git a/src/com/facebook/buck/junit/BuckBlockJUnit4ClassRunner.java b/src/com/facebook/buck/junit/BuckBlockJUnit4ClassRunner.java
index 48ec529..72a57b3 100644
--- a/src/com/facebook/buck/junit/BuckBlockJUnit4ClassRunner.java
+++ b/src/com/facebook/buck/junit/BuckBlockJUnit4ClassRunner.java
@@ -56,7 +56,8 @@
   // Executors.newSingleThreadExecutor(). The problem with Executors.newSingleThreadExecutor() is
   // that it does not let us specify a RejectedExecutionHandler, which we need to ensure that
   // garbage is not spewed to the user's console if the build fails.
-  private final ExecutorService executor = MoreExecutors.newSingleThreadExecutor();
+  private final ExecutorService executor =
+      MoreExecutors.newSingleThreadExecutor(getClass().getSimpleName());
 
   private final long defaultTestTimeoutMillis;
 
diff --git a/src/com/facebook/buck/junit/DelegateRunnerWithTimeout.java b/src/com/facebook/buck/junit/DelegateRunnerWithTimeout.java
index 7cbacb2..c159841 100644
--- a/src/com/facebook/buck/junit/DelegateRunnerWithTimeout.java
+++ b/src/com/facebook/buck/junit/DelegateRunnerWithTimeout.java
@@ -39,7 +39,8 @@
    * preserve the behavior of the {@code org.robolectric.RobolectricTestRunner}, we use an
    * {@link ExecutorService} with a single thread to run all of the tests.
    */
-  private static final ExecutorService executor = MoreExecutors.newSingleThreadExecutor();
+  private static final ExecutorService executor =
+      MoreExecutors.newSingleThreadExecutor(DelegateRunnerWithTimeout.class.getSimpleName());
 
   private final Runner delegate;
   private final long defaultTestTimeoutMillis;
diff --git a/src/com/facebook/buck/step/DefaultStepRunner.java b/src/com/facebook/buck/step/DefaultStepRunner.java
index a1826bd..a882df9 100644
--- a/src/com/facebook/buck/step/DefaultStepRunner.java
+++ b/src/com/facebook/buck/step/DefaultStepRunner.java
@@ -25,12 +25,13 @@
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
 
 import java.util.List;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
+
+import static com.facebook.buck.util.concurrent.MoreExecutors.newMultiThreadExecutor;
+import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
 
 public final class DefaultStepRunner implements StepRunner {
 
@@ -41,7 +42,8 @@
    * This StepRunner will run all steps on the same thread.
    */
   public DefaultStepRunner(ExecutionContext context) {
-    this(context, MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1)));
+    this(context,
+        listeningDecorator(newMultiThreadExecutor(DefaultStepRunner.class.getSimpleName(), 1)));
   }
 
   public DefaultStepRunner(ExecutionContext context,
diff --git a/src/com/facebook/buck/util/BUCK b/src/com/facebook/buck/util/BUCK
index 37b372c..44c5d66 100644
--- a/src/com/facebook/buck/util/BUCK
+++ b/src/com/facebook/buck/util/BUCK
@@ -36,6 +36,7 @@
   'MorePaths.java',
   'ProcessExecutor.java',
   'ProjectFilesystem.java',
+  'Threads.java',
   'Verbosity.java',
 ]
 java_library(
diff --git a/src/com/facebook/buck/util/BlockingHttpEndpoint.java b/src/com/facebook/buck/util/BlockingHttpEndpoint.java
index 6c3c3c7..3243b07 100644
--- a/src/com/facebook/buck/util/BlockingHttpEndpoint.java
+++ b/src/com/facebook/buck/util/BlockingHttpEndpoint.java
@@ -19,6 +19,7 @@
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
 
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -28,6 +29,7 @@
 import java.net.URL;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
@@ -42,6 +44,9 @@
   private URL url;
   private int timeout = DEFAULT_COMMON_TIMEOUT_MS;
   private final ListeningExecutorService requestService;
+  private static final ThreadFactory threadFactory =
+      new ThreadFactoryBuilder().setNameFormat(BlockingHttpEndpoint.class.getSimpleName() + "-%d")
+          .build();
 
   public BlockingHttpEndpoint(String url, int maxParallelRequests) throws MalformedURLException {
     this.url = new URL(url);
@@ -54,6 +59,7 @@
         2L,
         TimeUnit.MINUTES,
         workQueue,
+        threadFactory,
         new ThreadPoolExecutor.CallerRunsPolicy());
     requestService = MoreExecutors.listeningDecorator(executor);
   }
diff --git a/src/com/facebook/buck/util/ProcessExecutor.java b/src/com/facebook/buck/util/ProcessExecutor.java
index c246a40..2df73eb 100644
--- a/src/com/facebook/buck/util/ProcessExecutor.java
+++ b/src/com/facebook/buck/util/ProcessExecutor.java
@@ -88,9 +88,9 @@
         ansi);
 
     // Consume the streams so they do not deadlock.
-    Thread stdOutConsumer = new Thread(stdOut);
+    Thread stdOutConsumer = Threads.namedThread("ProcessExecutor (stdOut)", stdOut);
     stdOutConsumer.start();
-    Thread stdErrConsumer = new Thread(stdErr);
+    Thread stdErrConsumer = Threads.namedThread("ProcessExecutor (stdErr)", stdErr);
     stdErrConsumer.start();
 
     // Block until the Process completes.
diff --git a/src/com/facebook/buck/util/Threads.java b/src/com/facebook/buck/util/Threads.java
new file mode 100644
index 0000000..d04ed8c
--- /dev/null
+++ b/src/com/facebook/buck/util/Threads.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013-present Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.facebook.buck.util;
+
+public class Threads {
+
+  public static Thread namedThread(String name, Runnable runnable) {
+    Thread newThread = new Thread(runnable);
+    newThread.setName(name);
+    return newThread;
+  }
+}
diff --git a/src/com/facebook/buck/util/concurrent/MoreExecutors.java b/src/com/facebook/buck/util/concurrent/MoreExecutors.java
index ffd7227..88f9bd4 100644
--- a/src/com/facebook/buck/util/concurrent/MoreExecutors.java
+++ b/src/com/facebook/buck/util/concurrent/MoreExecutors.java
@@ -17,9 +17,12 @@
 package com.facebook.buck.util.concurrent;
 
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class MoreExecutors {
 
@@ -28,20 +31,52 @@
   }
 
   /**
+   * A ThreadFactory which gives each thread a meaningful and distinct name.
+   * ThreadFactoryBuilder is not used to avoid a dependency on Guava in the junit target.
+   */
+  private static class NamedThreadFactory implements ThreadFactory {
+
+    private final AtomicInteger threadCount = new AtomicInteger(0);
+    private final String threadName;
+
+    NamedThreadFactory(String threadName) {
+      this.threadName = threadName;
+    }
+
+    @Override
+    public Thread newThread(Runnable r) {
+      Thread newThread = Executors.defaultThreadFactory().newThread(r);
+      newThread.setName(String.format(threadName + "-%d", threadCount.incrementAndGet()));
+      return newThread;
+    }
+  }
+
+  /**
    * Creates a single threaded executor that silently discards rejected tasks. The problem with
    * {@link java.util.concurrent.Executors#newSingleThreadExecutor()} is that it does not let us
    * specify a RejectedExecutionHandler, which we need to ensure that garbage is not spewed to the
    * user's console if the build fails.
    *
    * @return A single-threaded executor that silently discards rejected tasks.
+   * @param threadName a thread name prefix used to easily identify threads when debugging.
    */
-  public static ExecutorService newSingleThreadExecutor() {
+  public static ExecutorService newSingleThreadExecutor(final String threadName) {
     return new ThreadPoolExecutor(
         /* corePoolSize */ 1,
         /* maximumPoolSize */ 1,
         /* keepAliveTime */ 0L, TimeUnit.MILLISECONDS,
         /* workQueue */ new LinkedBlockingQueue<Runnable>(),
+        /* threadFactory */ new NamedThreadFactory(threadName),
         /* handler */ new ThreadPoolExecutor.DiscardPolicy());
   }
 
+  /**
+   * Creates a multi-threaded executor with meaningfully named threads.
+   * @param threadName a thread name prefix used to easily identify threads when debugging.
+   * @param threadCount the number of threads that should be created in the pool.
+   * @return A multi-threaded executor.
+   */
+  public static ExecutorService newMultiThreadExecutor(final String threadName, int threadCount) {
+    return Executors.newFixedThreadPool(threadCount, new NamedThreadFactory(threadName));
+  }
 }
diff --git a/test/com/facebook/buck/step/BUCK b/test/com/facebook/buck/step/BUCK
index a922a24..b5c2c4a 100644
--- a/test/com/facebook/buck/step/BUCK
+++ b/test/com/facebook/buck/step/BUCK
@@ -34,6 +34,7 @@
     '//src/com/facebook/buck/step:step',
     '//src/com/facebook/buck/util:io',
     '//src/com/facebook/buck/util:util',
+    '//src/com/facebook/buck/util/concurrent:concurrent',
     '//src/com/facebook/buck/util/environment:environment',
     '//test/com/facebook/buck/event:testutil',
     '//test/com/facebook/buck/testutil:testutil',
diff --git a/test/com/facebook/buck/step/DefaultStepRunnerTest.java b/test/com/facebook/buck/step/DefaultStepRunnerTest.java
index 4d0ca12..1a3d7fe 100644
--- a/test/com/facebook/buck/step/DefaultStepRunnerTest.java
+++ b/test/com/facebook/buck/step/DefaultStepRunnerTest.java
@@ -30,16 +30,15 @@
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.google.common.util.concurrent.Uninterruptibles;
 
 import org.junit.Test;
 
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 
+import static com.facebook.buck.util.concurrent.MoreExecutors.newMultiThreadExecutor;
+import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
+
 public class DefaultStepRunnerTest {
 
   @Test
@@ -59,12 +58,8 @@
         .setPlatform(Platform.detect())
         .build();
 
-    ThreadFactory threadFactory = new ThreadFactoryBuilder()
-        .setDaemon(true)
-        .setNameFormat(getClass().getSimpleName() + "-%d")
-        .build();
-    ListeningExecutorService executorService = MoreExecutors.listeningDecorator(
-        Executors.newFixedThreadPool(3, threadFactory));
+    ListeningExecutorService executorService =
+        listeningDecorator(newMultiThreadExecutor(getClass().getSimpleName(), 3));
     DefaultStepRunner runner = new DefaultStepRunner(context, executorService);
     runner.runStep(passingStep);
     try {
@@ -104,12 +99,9 @@
         .setEventBus(BuckEventBusFactory.newInstance())
         .setPlatform(Platform.detect())
         .build();
-    ThreadFactory threadFactory = new ThreadFactoryBuilder()
-        .setDaemon(true)
-        .setNameFormat(getClass().getSimpleName() + "-%d")
-        .build();
-    ListeningExecutorService executorService = MoreExecutors.listeningDecorator(
-        Executors.newFixedThreadPool(3, threadFactory));
+
+    ListeningExecutorService executorService =
+        listeningDecorator(newMultiThreadExecutor(getClass().getSimpleName(), 3));
     DefaultStepRunner runner = new DefaultStepRunner(context, executorService);
     runner.runStepsInParallelAndWait(steps.build());