11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2010 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.util.concurrent;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkArgument;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.Thread.UncaughtExceptionHandler;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executors;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ThreadFactory;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicLong;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * A ThreadFactory builder, providing any combination of these features:
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <ul>
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li> whether threads should be marked as {@linkplain Thread#setDaemon daemon}
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * threads
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li> a {@linkplain ThreadFactoryBuilder#setNameFormat naming format}
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li> a {@linkplain Thread#setPriority thread priority}
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li> an {@linkplain Thread#setUncaughtExceptionHandler uncaught exception
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * handler}
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li> a {@linkplain ThreadFactory#newThread backing thread factory}
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </ul>
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * If no backing thread factory is provided, a default backing thread factory is
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * used as if by calling {@code setThreadFactory(}{@link
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Executors#defaultThreadFactory()}{@code )}.
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Kurt Alfred Kluever
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 4.0
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic final class ThreadFactoryBuilder {
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private String nameFormat = null;
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private Boolean daemon = null;
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private Integer priority = null;
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private UncaughtExceptionHandler uncaughtExceptionHandler = null;
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private ThreadFactory backingThreadFactory = null;
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a new {@link ThreadFactory} builder.
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public ThreadFactoryBuilder() {}
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Sets the naming format to use when naming threads ({@link Thread#setName})
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * which are created with this ThreadFactory.
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param nameFormat a {@link String#format(String, Object...)}-compatible
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *     format String, to which a unique integer (0, 1, etc.) will be supplied
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *     as the single parameter. This integer will be unique to the built
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *     instance of the ThreadFactory and will be assigned sequentially.
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return this for the builder pattern
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public ThreadFactoryBuilder setNameFormat(String nameFormat) {
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    String.format(nameFormat, 0); // fail fast if the format is bad or null
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.nameFormat = nameFormat;
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return this;
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Sets daemon or not for new threads created with this ThreadFactory.
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param daemon whether or not new Threads created with this ThreadFactory
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *     will be daemon threads
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return this for the builder pattern
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public ThreadFactoryBuilder setDaemon(boolean daemon) {
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.daemon = daemon;
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return this;
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Sets the priority for new threads created with this ThreadFactory.
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param priority the priority for new Threads created with this
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *     ThreadFactory
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return this for the builder pattern
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public ThreadFactoryBuilder setPriority(int priority) {
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Thread#setPriority() already checks for validity. These error messages
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // are nicer though and will fail-fast.
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkArgument(priority >= Thread.MIN_PRIORITY,
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "Thread priority (%s) must be >= %s", priority, Thread.MIN_PRIORITY);
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkArgument(priority <= Thread.MAX_PRIORITY,
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "Thread priority (%s) must be <= %s", priority, Thread.MAX_PRIORITY);
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.priority = priority;
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return this;
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Sets the {@link UncaughtExceptionHandler} for new threads created with this
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * ThreadFactory.
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param uncaughtExceptionHandler the uncaught exception handler for new
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *     Threads created with this ThreadFactory
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return this for the builder pattern
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public ThreadFactoryBuilder setUncaughtExceptionHandler(
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      UncaughtExceptionHandler uncaughtExceptionHandler) {
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.uncaughtExceptionHandler = checkNotNull(uncaughtExceptionHandler);
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return this;
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Sets the backing {@link ThreadFactory} for new threads created with this
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * ThreadFactory. Threads will be created by invoking #newThread(Runnable) on
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * this backing {@link ThreadFactory}.
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param backingThreadFactory the backing {@link ThreadFactory} which will
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *     be delegated to during thread creation.
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return this for the builder pattern
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @see MoreExecutors
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public ThreadFactoryBuilder setThreadFactory(
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ThreadFactory backingThreadFactory) {
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.backingThreadFactory = checkNotNull(backingThreadFactory);
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return this;
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a new thread factory using the options supplied during the building
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * process. After building, it is still possible to change the options used to
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * build the ThreadFactory and/or build again. State is not shared amongst
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * built instances.
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return the fully constructed {@link ThreadFactory}
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public ThreadFactory build() {
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return build(this);
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static ThreadFactory build(ThreadFactoryBuilder builder) {
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final String nameFormat = builder.nameFormat;
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Boolean daemon = builder.daemon;
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Integer priority = builder.priority;
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final UncaughtExceptionHandler uncaughtExceptionHandler =
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        builder.uncaughtExceptionHandler;
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ThreadFactory backingThreadFactory =
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        (builder.backingThreadFactory != null)
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ? builder.backingThreadFactory
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        : Executors.defaultThreadFactory();
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicLong count = (nameFormat != null) ? new AtomicLong(0) : null;
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new ThreadFactory() {
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Thread newThread(Runnable runnable) {
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Thread thread = backingThreadFactory.newThread(runnable);
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (nameFormat != null) {
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          thread.setName(String.format(nameFormat, count.getAndIncrement()));
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (daemon != null) {
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          thread.setDaemon(daemon);
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (priority != null) {
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          thread.setPriority(priority);
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (uncaughtExceptionHandler != null) {
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return thread;
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
177