net.pms.util.BasicThreadFactory.java Source code

Java tutorial

Introduction

Here is the source code for net.pms.util.BasicThreadFactory.java

Source

/*
 * Universal Media Server, for streaming any media to DLNA
 * compatible renderers based on the http://www.ps3mediaserver.org.
 * Copyright (C) 2012 UMS developers.
 *
 * This program is a free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; version 2
 * of the License only.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package net.pms.util;

import static org.apache.commons.lang3.StringUtils.isBlank;
import java.util.Locale;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * A {@link ThreadFactory} implementing a simple name structure.
 *
 * @author Nadahar
 */
public class BasicThreadFactory implements ThreadFactory {
    /** A static thread-safe pool number counter. */
    protected static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);

    /** The pool number for this instance. */
    protected final int instancePoolNumber;

    /** The {@link ThreadGroup}. */
    protected final ThreadGroup group;

    /** The thread number counter. */
    protected final AtomicInteger threadNumber = new AtomicInteger(1);

    /** The thread priority. */
    protected final int threadPriority;

    /** The name pattern. */
    protected final String namePattern;

    /** The number of variables in {@code namePattern}. */
    protected final int numVariables;

    /**
     * Creates a new {@link BasicThreadFactory} using the default
     * {@link ThreadGroup} and priority {@link Thread#NORM_PRIORITY}.
     * <p>
     * The {@link Thread} names generated by the new {@link BasicThreadFactory}
     * is created by calling {@link String#format} with {@code namePattern} as
     * the "format" and pool- and thread number as arguments. The formatting
     * rules are those of {@link java.util.Formatter}.
     * <p>
     * No more than two variables of type {@code %d} or {@code %s} is allowed in
     * {@code namePattern}, and they will be substituted as follows:
     * <ul>
     * <li>No variables: All {@link Thread} names generated by this
     * {@link ThreadFactory} will be equal to {@code namePattern}.</li>
     * <li>One variable: Only thread number will be used, pool number isn't
     * used.</li>
     * <li>Two variables: Pool number will be used for the first variable in
     * {@code namePattern}, thread number for the second.
     * </ul>
     *
     * @param namePattern The {@link java.util.Formatter} formatted
     *            {@link String} from which to generate {@link Thread} names.
     */
    public BasicThreadFactory(String namePattern) {
        this(namePattern, Thread.NORM_PRIORITY, null);
    }

    /**
     * Creates a new {@link BasicThreadFactory} using the given arguments and
     * the default {@link ThreadGroup}.
     * <p>
     * The {@link Thread} names generated by the new {@link BasicThreadFactory}
     * is created by calling {@link String#format} with {@code namePattern} as
     * the "format" and pool- and thread number as arguments. The formatting
     * rules are those of {@link java.util.Formatter}.
     * <p>
     * No more than two variables of type {@code %d} or {@code %s} is allowed in
     * {@code namePattern}, and they will be substituted as follows:
     * <ul>
     * <li>No variables: All {@link Thread} names generated by this
     * {@link ThreadFactory} will be equal to {@code namePattern}.</li>
     * <li>One variable: Only thread number will be used, pool number isn't
     * used.</li>
     * <li>Two variables: Pool number will be used for the first variable in
     * {@code namePattern}, thread number for the second.
     * </ul>
     *
     * @param namePattern The {@link java.util.Formatter} formatted
     *            {@link String} from which to generate {@link Thread} names.
     * @param threadPriority The {@link Thread} priority.
     */
    public BasicThreadFactory(String namePattern, int threadPriority) {
        this(namePattern, threadPriority, null);
    }

    /**
     * Creates a new {@link BasicThreadFactory} using the given arguments and
     * priority {@link Thread#NORM_PRIORITY}.
     * <p>
     * The {@link Thread} names generated by the new {@link BasicThreadFactory}
     * is created by calling {@link String#format} with {@code namePattern} as
     * the "format" and pool- and thread number as arguments. The formatting
     * rules are those of {@link java.util.Formatter}.
     * <p>
     * No more than two variables of type {@code %d} or {@code %s} is allowed in
     * {@code namePattern}, and they will be substituted as follows:
     * <ul>
     * <li>No variables: All {@link Thread} names generated by this
     * {@link ThreadFactory} will be equal to {@code namePattern}.</li>
     * <li>One variable: Only thread number will be used, pool number isn't
     * used.</li>
     * <li>Two variables: Pool number will be used for the first variable in
     * {@code namePattern}, thread number for the second.
     * </ul>
     *
     * @param namePattern The {@link java.util.Formatter} formatted
     *            {@link String} from which to generate {@link Thread} names.
     * @param group The {@link ThreadGroup}.
     */
    public BasicThreadFactory(String namePattern, ThreadGroup group) {
        this(namePattern, Thread.NORM_PRIORITY, group);
    }

    /**
     * Creates a new {@link BasicThreadFactory} using the given arguments.
     * <p>
     * The {@link Thread} names generated by the new {@link BasicThreadFactory}
     * is created by calling {@link String#format} with {@code namePattern} as
     * the "format" and pool- and thread number as arguments. The formatting
     * rules are those of {@link java.util.Formatter}.
     * <p>
     * No more than two variables of type {@code %d} or {@code %s} is allowed in
     * {@code namePattern}, and they will be substituted as follows:
     * <ul>
     * <li>No variables: All {@link Thread} names generated by this
     * {@link ThreadFactory} will be equal to {@code namePattern}.</li>
     * <li>One variable: Only thread number will be used, pool number isn't
     * used.</li>
     * <li>Two variables: Pool number will be used for the first variable in
     * {@code namePattern}, thread number for the second.
     * </ul>
     *
     * @param namePattern The {@link java.util.Formatter} formatted
     *            {@link String} from which to generate {@link Thread} names.
     * @param threadPriority The {@link Thread} priority.
     * @param group The {@link ThreadGroup}.
     */
    public BasicThreadFactory(String namePattern, int threadPriority, ThreadGroup group) {
        if (isBlank(namePattern)) {
            throw new IllegalArgumentException("namePattern cannot be blank");
        }
        if (group == null) {
            SecurityManager securityManager = System.getSecurityManager();
            group = (securityManager != null) ? securityManager.getThreadGroup()
                    : Thread.currentThread().getThreadGroup();
        }
        this.group = group;
        this.threadPriority = Math.min(Thread.MAX_PRIORITY, Math.max(Thread.MIN_PRIORITY, threadPriority));
        int pctSes = 0;
        int pctDs = 0;
        int i = 0;
        while (true) {
            i = namePattern.indexOf("%s", i);
            if (i >= 0) {
                pctSes++;
                i++;
            } else {
                break;
            }
        }
        while (true) {
            i = namePattern.indexOf("%d", i);
            if (i >= 0) {
                pctDs++;
                i++;
            } else {
                break;
            }
        }
        if (pctSes + pctDs > 2) {
            throw new IllegalArgumentException("namePattern can't have more than 2 variables");
        }
        this.numVariables = pctSes + pctDs;
        this.namePattern = namePattern;
        if (numVariables == 2) {
            this.instancePoolNumber = POOL_NUMBER.getAndIncrement();
        } else {
            this.instancePoolNumber = 0;
        }
    }

    @Override
    public Thread newThread(Runnable runnable) {
        String threadName;
        switch (numVariables) {
        case 0:
            threadName = namePattern;
            break;
        case 1:
            threadName = String.format(Locale.ROOT, namePattern, threadNumber.getAndIncrement());
            break;
        default:
            threadName = String.format(Locale.ROOT, namePattern, instancePoolNumber,
                    threadNumber.getAndIncrement());
        }
        Thread thread = new Thread(group, runnable, threadName, 0);
        if (thread.isDaemon()) {
            thread.setDaemon(false);
        }
        if (thread.getPriority() != threadPriority) {
            thread.setPriority(threadPriority);
        }
        return thread;
    }

}