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