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

net.tascalate.concurrent.TaskExecutors Maven / Gradle / Ivy

Go to download

Implementation of blocking (IO-Bound) cancellable java.util.concurrent.CompletionStage and related extensions to java.util.concurrent.ExecutorService-s

There is a newer version: 0.9.8
Show newest version
/**
 * Copyright 2015-2019 Valery Silaev (http://vsilaev.com)
 *
 * 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.tascalate.concurrent;

import java.util.Collection;
import java.util.List;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * The drop-in replacement for {@link Executors} utility class that returns various useful implementations
 * of {@link TaskExecutorService} instead of standard {@link ExecutorService}.
 * @author vsilaev
 *
 */
public class TaskExecutors {
    /**
     * Creates a thread pool that reuses a fixed number of threads operating off
     * a shared unbounded queue. At any point, at most {@code nThreads} threads
     * will be active processing tasks. If additional tasks are submitted when
     * all threads are active, they will wait in the queue until a thread is
     * available. If any thread terminates due to a failure during execution
     * prior to shutdown, a new one will take its place if needed to execute
     * subsequent tasks. The threads in the pool will exist until it is
     * explicitly {@link ExecutorService#shutdown shutdown}.
     *
     * @param nThreads
     *            the number of threads in the pool
     * @return the newly created thread pool
     * @throws IllegalArgumentException
     *             if {@code nThreads <= 0}
     */
    public static TaskExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolTaskExecutor(nThreads, nThreads, 
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue());
    }

    /**
     * Creates a thread pool that reuses a fixed number of threads operating off
     * a shared unbounded queue, using the provided ThreadFactory to create new
     * threads when needed. At any point, at most {@code nThreads} threads will
     * be active processing tasks. If additional tasks are submitted when all
     * threads are active, they will wait in the queue until a thread is
     * available. If any thread terminates due to a failure during execution
     * prior to shutdown, a new one will take its place if needed to execute
     * subsequent tasks. The threads in the pool will exist until it is
     * explicitly {@link ExecutorService#shutdown shutdown}.
     *
     * @param nThreads
     *            the number of threads in the pool
     * @param threadFactory
     *            the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException
     *             if threadFactory is null
     * @throws IllegalArgumentException
     *             if {@code nThreads <= 0}
     */
    public static TaskExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolTaskExecutor(nThreads, nThreads, 
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue(), threadFactory);
    }

    /**
     * Creates a thread pool that creates new threads as needed, but will reuse
     * previously constructed threads when they are available. These pools will
     * typically improve the performance of programs that execute many
     * short-lived asynchronous tasks. Calls to {@code execute} will reuse
     * previously constructed threads if available. If no existing thread is
     * available, a new thread will be created and added to the pool. Threads
     * that have not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will not
     * consume any resources. Note that pools with similar properties but
     * different details (for example, timeout parameters) may be created using
     * {@link ThreadPoolExecutor} constructors.
     *
     * @return the newly created thread pool
     */
    public static TaskExecutorService newCachedThreadPool() {
        return new ThreadPoolTaskExecutor(0, Integer.MAX_VALUE, 
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue());
    }

    /**
     * Creates a thread pool that creates new threads as needed, but will reuse
     * previously constructed threads when they are available, and uses the
     * provided ThreadFactory to create new threads when needed.
     * 
     * @param threadFactory
     *            the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException
     *             if threadFactory is null
     */
    public static TaskExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolTaskExecutor(0, Integer.MAX_VALUE, 
                                          60L, TimeUnit.SECONDS, 
                                          new SynchronousQueue(),
                                          threadFactory);
    }

    /**
     * Creates an Executor that uses a single worker thread operating off an
     * unbounded queue. (Note however that if this single thread terminates due
     * to a failure during execution prior to shutdown, a new one will take its
     * place if needed to execute subsequent tasks.) Tasks are guaranteed to
     * execute sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent {@code newFixedThreadPool(1)}
     * the returned executor is guaranteed not to be reconfigurable to use
     * additional threads.
     *
     * @return the newly created single-threaded Executor
     */
    public static TaskExecutorService newSingleThreadExecutor() {
        return adapt(Executors.newSingleThreadExecutor());
    }

    /**
     * Creates an Executor that uses a single worker thread operating off an
     * unbounded queue, and uses the provided ThreadFactory to create a new
     * thread when needed. Unlike the otherwise equivalent
     * {@code newFixedThreadPool(1, threadFactory)} the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     *
     * @param threadFactory
     *            the factory to use when creating new threads
     *
     * @return the newly created single-threaded Executor
     * @throws NullPointerException
     *             if threadFactory is null
     */
    public static TaskExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return adapt(Executors.newSingleThreadExecutor(threadFactory));
    }

    public static TaskExecutorService adapt(ExecutorService executorService) {
        if (executorService instanceof TaskExecutorService) {
            return (TaskExecutorService) executorService;
        } else {
            return new TaskExecutorServiceAdapter(executorService);
        }
    }

    static class TaskExecutorServiceAdapter implements TaskExecutorService {
        private final ExecutorService delegate;

        TaskExecutorServiceAdapter(ExecutorService executor) {
            delegate = executor;
        }

        public void execute(Runnable command) {
            delegate.execute(command);
        }

        public void shutdown() {
            delegate.shutdown();
        }

        public List shutdownNow() {
            return delegate.shutdownNow();
        }

        public boolean isShutdown() {
            return delegate.isShutdown();
        }

        public boolean isTerminated() {
            return delegate.isTerminated();
        }

        public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
            return delegate.awaitTermination(timeout, unit);
        }

        public  Promise submit(Callable callable) {
            CompletableTask task = createTask(callable);
            delegate.execute(task);
            return task;
        }

        public  Promise submit(Runnable codeBlock, T result) {
            CompletableTask task = createTask(Executors.callable(codeBlock, result));
            delegate.execute(task);
            return task;
        }

        public Promise submit(Runnable codeBlock) {
            CompletableTask task = createTask(Executors.callable(codeBlock, null));
            delegate.execute(task);
            return task;
        }

        public  List> invokeAll(Collection> tasks) throws InterruptedException {
            return delegate.invokeAll(tasks);
        }

        public  List> invokeAll(Collection> tasks, 
                                             long timeout, TimeUnit unit) throws InterruptedException {
            
            return delegate.invokeAll(tasks, timeout, unit);
        }

        public  T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException {
            return delegate.invokeAny(tasks);
        }

        public  T invokeAny(Collection> tasks, 
                               long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
            
            return delegate.invokeAny(tasks, timeout, unit);
        }

        protected  CompletableTask createTask(Callable callable) {
            return new CompletableTask(this, callable);
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy