/* * Copyright 2013 Cameron Beccario * * 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 net.nullschool.util; import java.util.IllegalFormatException; import java.util.Objects; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** * 2013-02-09<p/> * * Utility methods for operating on threads. * * @author Cameron Beccario */ public class ThreadTools { private ThreadTools() { throw new AssertionError(); } /** * Returns a {@link ThreadFactory} that configures threads constructed by an existing ThreadFactory as * {@link Thread#setDaemon daemon threads}. * * @param wrapped the thread factory to wrap. * @return a daemon thread factory. * @throws NullPointerException if {@code wrapped} is null. */ public static ThreadFactory newDaemonThreadFactory(final ThreadFactory wrapped) { Objects.requireNonNull(wrapped); return new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = wrapped.newThread(r); if (!t.isDaemon()) { t.setDaemon(true); } return t; } }; } /** * Returns a {@link ThreadFactory} that configures threads constructed by an existing ThreadFactory with * names using the given format string, as described by {@link String#format}. The {@code format} string * can optionally make use of two substitutions: 1) an integer that increments upon each call to * {@link ThreadFactory#newThread}, and 2) the name of the thread as originally assigned by the wrapped * thread factory. For example, the format string {@code "Thread %s"} will cause this ThreadFactory to name * the resulting threads "Thread 0", "Thread 1", ... and so on. * * @param format the format string to be used for naming new threads. * @param wrapped the thread factory to wrap. * @return a thread factory that names threads according to the specified format. * @throws NullPointerException if {@code wrapped} or {@code format} is null. * @throws IllegalFormatException if {@code format} contains illegal syntax or is incompatible with the * described substitutions. */ public static ThreadFactory newNamingThreadFactory(final String format, final ThreadFactory wrapped) { // noinspection ResultOfMethodCallIgnored String.format(format, 0, "test name"); // make sure the format string will work Objects.requireNonNull(wrapped); final AtomicInteger threadNumber = new AtomicInteger(0); return new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = wrapped.newThread(r); t.setName(String.format(format, threadNumber.getAndIncrement(), t.getName())); return t; } }; } /** * Returns a {@link ThreadFactory} that configures threads constructed by an existing ThreadFactory with * the specified {@link Thread#setContextClassLoader context ClassLoader}. A null {@code classLoader} * indicates the system class loader. * * @param wrapped the thread factory to wrap. * @return a thread factory that configures new threads with a specific context ClassLoader. * @throws NullPointerException if {@code wrapped} is null. */ public static ThreadFactory newContextThreadFactory(final ClassLoader classLoader, final ThreadFactory wrapped) { Objects.requireNonNull(wrapped); return new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = wrapped.newThread(r); t.setContextClassLoader(classLoader); return t; } }; } }