All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.sshd.common.util.threads.ThreadUtils Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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 org.apache.sshd.common.util.threads;

import java.io.IOException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

import org.apache.sshd.common.util.ReflectionUtils;
import org.apache.sshd.common.util.io.functors.IOFunction;

/**
 * Utility class for thread pools.
 *
 * @author Apache MINA SSHD Project
 */
public final class ThreadUtils {

    /**
     * Marks framework-internal threads.
     */
    private static final ThreadLocal IS_INTERNAL_THREAD = new ThreadLocal<>();

    private ThreadUtils() {
        throw new UnsupportedOperationException("No instance");
    }

    /**
     * Runs a piece of code given as a {@link Callable} with a flag set indicating that the executing thread is an
     * Apache MINA sshd framework-internal thread.
     *
     * @param         return type
     * @param  code      code to run
     * @return           the result of {@code code}
     * @throws Exception propagated from {@code code.call()}
     * @see              #isInternalThread()
     */
    public static  V runAsInternal(Callable code) throws Exception {
        if (isInternalThread()) {
            return code.call();
        }
        try {
            IS_INTERNAL_THREAD.set(Boolean.TRUE);
            return code.call();
        } finally {
            IS_INTERNAL_THREAD.remove();
        }
    }

    /**
     * Runs an {@link IOFunction} with a flag set indicating that the executing thread is an Apache MINA sshd
     * framework-internal thread.
     *
     * @param           parameter type
     * @param           return type
     * @param  param       parameter for the function
     * @param  code        function to run
     * @return             the result of {@code code}
     * @throws IOException propagated from {@code code.apply()}
     * @see                #isInternalThread()
     */
    public static  V runAsInternal(T param, IOFunction code) throws IOException {
        if (isInternalThread()) {
            return code.apply(param);
        }
        try {
            IS_INTERNAL_THREAD.set(Boolean.TRUE);
            return code.apply(param);
        } finally {
            IS_INTERNAL_THREAD.remove();
        }
    }

    /**
     * Tells whether the calling thread is an Apache MINA sshd framework-internal thread.
     *
     * @return {@code true} if the thread is considered internal to the framework; {@code false} if not
     * @see    #runAsInternal(Callable)
     */
    public static boolean isInternalThread() {
        return Boolean.TRUE.equals(IS_INTERNAL_THREAD.get());
    }

    /**
     * Wraps an {@link CloseableExecutorService} in such a way as to "protect" it for calls to the
     * {@link CloseableExecutorService#shutdown()} or {@link CloseableExecutorService#shutdownNow()}. All other calls
     * are delegated as-is to the original service. Note: the exposed wrapped proxy will answer correctly the
     * {@link CloseableExecutorService#isShutdown()} query if indeed one of the {@code shutdown} methods was invoked.
     *
     * @param  executorService The original service - ignored if {@code null}
     * @param  shutdownOnExit  If {@code true} then it is OK to shutdown the executor so no wrapping takes place.
     * @return                 Either the original service or a wrapped one - depending on the value of the
     *                         shutdownOnExit parameter
     */
    public static CloseableExecutorService protectExecutorServiceShutdown(
            CloseableExecutorService executorService, boolean shutdownOnExit) {
        if (executorService == null || shutdownOnExit || executorService instanceof NoCloseExecutor) {
            return executorService;
        }
        return new NoCloseExecutor(executorService);
    }

    public static CloseableExecutorService noClose(CloseableExecutorService executorService) {
        return protectExecutorServiceShutdown(executorService, false);
    }

    public static ClassLoader resolveDefaultClassLoader(Object anchor) {
        return resolveDefaultClassLoader((anchor == null) ? null : anchor.getClass());
    }

    public static Iterable resolveDefaultClassLoaders(Object anchor) {
        return resolveDefaultClassLoaders((anchor == null) ? null : anchor.getClass());
    }

    public static Iterable resolveDefaultClassLoaders(Class anchor) {
        return () -> iterateDefaultClassLoaders(anchor);
    }

    public static Class resolveDefaultClass(Class anchor, String className) {
        return resolveDefaultClass(resolveDefaultClassLoaders(anchor), className);
    }

    public static Class resolveDefaultClass(Iterable cls, String className) {
        for (ClassLoader cl : cls) {
            try {
                return cl.loadClass(className);
            } catch (Throwable ignored) {
                // Ignore
            }
        }
        return null;
    }

    public static  T createDefaultInstance(
            Class anchor, Class targetType, String className)
            throws ReflectiveOperationException {
        return createDefaultInstance(resolveDefaultClassLoaders(anchor), targetType, className);
    }

    public static  T createDefaultInstance(
            ClassLoader cl, Class targetType, String className)
            throws ReflectiveOperationException {
        Class instanceType = cl.loadClass(className);
        return ReflectionUtils.newInstance(instanceType, targetType);
    }

    public static  T createDefaultInstance(
            Iterable cls, Class targetType, String className)
            throws ReflectiveOperationException {
        for (ClassLoader cl : cls) {
            try {
                return createDefaultInstance(cl, targetType, className);
            } catch (ClassNotFoundException e) {
                // Ignore
            }
        }
        throw new ClassNotFoundException(className);
    }

    /**
     * 

* Attempts to find the most suitable {@link ClassLoader} as follows: *

*
    *
  • *

    * Check the {@link Thread#getContextClassLoader()} value *

    *
  • * *
  • *

    * If no thread context class loader then check the anchor class (if given) for its class loader *

    *
  • * *
  • *

    * If still no loader available, then use {@link ClassLoader#getSystemClassLoader()} *

    *
  • *
* * @param anchor The anchor {@link Class} to use if no current thread context class loader - ignored if * {@code null} * * @return The resolved {@link ClassLoader} - Note: might still be {@code null} if went all the way * "down" to the system class loader and it was also {@code null}. */ public static ClassLoader resolveDefaultClassLoader(Class anchor) { Thread thread = Thread.currentThread(); ClassLoader cl = thread.getContextClassLoader(); if (cl != null) { return cl; } if (anchor != null) { cl = anchor.getClassLoader(); } if (cl == null) { // can happen for core Java classes cl = ClassLoader.getSystemClassLoader(); } return cl; } public static Iterator iterateDefaultClassLoaders(Class anchor) { Class effectiveAnchor = (anchor == null) ? ThreadUtils.class : anchor; return new Iterator() { @SuppressWarnings({ "unchecked", "checkstyle:Indentation" }) private final Supplier[] suppliers = new Supplier[] { () -> { Thread thread = Thread.currentThread(); return thread.getContextClassLoader(); }, effectiveAnchor::getClassLoader, ClassLoader::getSystemClassLoader }; private int index; @Override public boolean hasNext() { for (; index < suppliers.length; index++) { Supplier scl = suppliers[index]; ClassLoader cl = scl.get(); if (cl != null) { return true; } } return false; } @Override public ClassLoader next() { if (index >= suppliers.length) { throw new NoSuchElementException("All elements exhausted"); } Supplier scl = suppliers[index]; index++; return scl.get(); } }; } public static CloseableExecutorService newFixedThreadPoolIf( CloseableExecutorService executorService, String poolName, int nThreads) { return executorService == null ? newFixedThreadPool(poolName, nThreads) : executorService; } public static CloseableExecutorService newFixedThreadPool(String poolName, int nThreads) { return new SshThreadPoolExecutor( nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, // TODO make this configurable new LinkedBlockingQueue<>(), new SshdThreadFactory(poolName), new ThreadPoolExecutor.CallerRunsPolicy()); } public static CloseableExecutorService newCachedThreadPoolIf( CloseableExecutorService executorService, String poolName) { return executorService == null ? newCachedThreadPool(poolName) : executorService; } public static CloseableExecutorService newCachedThreadPool(String poolName) { return new SshThreadPoolExecutor( 0, Integer.MAX_VALUE, // TODO make this configurable 60L, TimeUnit.SECONDS, // TODO make this configurable new SynchronousQueue<>(), new SshdThreadFactory(poolName), new ThreadPoolExecutor.CallerRunsPolicy()); } public static ScheduledExecutorService newSingleThreadScheduledExecutor(String poolName) { return new ScheduledThreadPoolExecutor(1, new SshdThreadFactory(poolName)); } public static CloseableExecutorService newSingleThreadExecutor(String poolName) { return newFixedThreadPool(poolName, 1); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy