kr.debop4j.core.parallelism.AsyncTool.java Source code

Java tutorial

Introduction

Here is the source code for kr.debop4j.core.parallelism.AsyncTool.java

Source

/*
 * Copyright 2011-2013 the original author or authors.
 *
 * 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 kr.debop4j.core.parallelism;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import kr.debop4j.core.Action1;
import kr.debop4j.core.Function1;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.*;

import static kr.debop4j.core.Guard.shouldNotBeNull;

/**
 * ?   Utility Class
 *
 * @author ? ( sunghyouk.bae@gmail.com )
 * @since 12. 9. 14
 */
@Slf4j
@SuppressWarnings("unchecked")
public abstract class AsyncTool {

    /** ?? */
    private AsyncTool() {
    }

    private static final ExecutorService executor = Executors
            .newScheduledThreadPool(Runtime.getRuntime().availableProcessors() * 2);

    public static final Runnable EMPTY_RUNNABLE = new Runnable() {
        @Override
        public void run() {
            log.trace("EMPTY_RUNNABLE is run.");
        }
    };

    /**
     *  callable ? ?? ,   FutureTask .
     * {@link java.util.concurrent.FutureTask#run()} ?  .
     *
     * @param callable the callable
     * @return the future task
     */
    public static <T> FutureTask<T> newTask(final Callable<T> callable) {
        return new FutureTask<T>(callable);
    }

    /**
     *  runnable ? , FutureTask  .
     * {@link java.util.concurrent.FutureTask#run()} ?  .
     *
     * @param runnable the runnable
     * @param result   the result
     * @return the future task
     */
    public static <T> FutureTask<T> newTask(final Runnable runnable, final T result) {
        return new FutureTask<T>(runnable, result);
    }

    /**
     *  runnable ? , Future  .
     * {@link java.util.concurrent.FutureTask#run()} ?  .
     *
     * @param runnable the runnable
     * @return the future task
     */
    public static FutureTask<Void> newTask(final Runnable runnable) {
        return new FutureTask<Void>(runnable, null);
    }

    /**
     *  ? ?, ?? .
     *
     * @param callable the callable
     * @return the future
     */
    public static <T> Future<T> startNew(final Callable<T> callable) {
        return executor.submit(callable);
    }

    /**
     *  ? ?, ? .
     *
     * @param runnable the runnable
     * @param result   the result
     * @return the future
     */
    public static <T> Future<T> startNew(final Runnable runnable, final T result) {
        return executor.submit(runnable, result);
    }

    /**
     * prevTask  ?, action? .
     *
     * @param prevTask the prev task
     * @param action   the action
     * @param result   the result
     * @return the future
     */
    public static <T, V> Future<V> continueTask(final FutureTask<T> prevTask, final Action1<T> action,
            final @Nullable V result) {
        final Callable<V> chainTask = new Callable<V>() {
            @Override
            public V call() throws Exception {
                T prev = prevTask.get();
                action.perform(prev);
                return result;
            }
        };

        return startNew(chainTask);
    }

    /**
     * prevTask?   ?  ? function?   .
     *
     * @param prevTask the prev task
     * @param function the function
     * @return the future
     */
    public static <T, V> Future<V> continueTask(final FutureTask<T> prevTask, final Function1<T, V> function) {
        return startNew(new Callable<V>() {
            @Override
            public V call() throws Exception {
                return function.execute(prevTask.get());
            }
        });
    }

    /**
     * Gets task has result.
     *
     * @param result the result
     * @return the task has result
     */
    public static <T> FutureTask<T> getTaskHasResult(final T result) {
        return newTask(EMPTY_RUNNABLE, result);
    }

    /**
     *   ??   ,   {@link java.util.concurrent.FutureTask} ?  .
     *
     * @param elements the elements
     * @param function the function
     * @return the list
     * @throws InterruptedException the interrupted exception
     */
    public static <T, R> List<Future<R>> runAsync(final Iterable<? extends T> elements,
            final Function1<T, R> function) throws InterruptedException {
        shouldNotBeNull(function, "function");

        final List<Callable<R>> tasks = Lists.newArrayList();

        for (final T element : elements) {
            Callable<R> task = new Callable<R>() {
                @Override
                public R call() throws Exception {
                    return function.execute(element);
                }
            };
            tasks.add(task);
        }
        return executor.invokeAll(tasks);
    }

    /**
     * Invoke all.
     *
     * @param tasks the tasks
     * @throws InterruptedException the interrupted exception
     */
    public static <T> void invokeAll(final Collection<? extends Callable<T>> tasks) throws InterruptedException {
        getAll(executor.invokeAll(tasks));
    }

    /**
     * Invoke all.
     *
     * @param tasks   the tasks
     * @param timeout the timeout
     * @param unit    the unit
     * @throws InterruptedException the interrupted exception
     */
    public static <T> void invokeAll(final Collection<? extends Callable<T>> tasks, final long timeout,
            final TimeUnit unit) throws InterruptedException {
        getAll(executor.invokeAll(tasks, timeout, unit));
    }

    /** ? ? , ? ? ? . */
    public static <T> void runAll(final Iterable<? extends Future<T>> tasks) {

        log.trace("? ? ?  ...");

        getAll(tasks);

        log.trace("? ? ?  ?!!!");
    }

    /**
     * ?  ?? ? ?  . (??  ? ,  ? ??.)
     *
     * @param tasks  
     * @param <T>     
     * @return   
     */
    public static <T> List<T> getAll(final Iterable<? extends Future<T>> tasks) {

        log.trace("? ?  ...");

        final List<T> results = new CopyOnWriteArrayList<>();

        try {
            for (Future<T> future : tasks) {
                results.add(future.get());
            }
        } catch (Exception e) {
            log.error("?    ?.", e);
            throw new RuntimeException(e);
        }
        return results;
    }

    /**
     * ?  ?? ? ?  . (??  ? ,  ? ??.)
     *
     * @param tasks    
     * @param timeout  
     * @param unit     ? 
     * @param <T>     
     * @return  
     */
    public static <T> List<T> getAll(final Iterable<? extends Future<T>> tasks, final long timeout,
            final TimeUnit unit) {

        log.trace("? ?  ... timeout=[{}], unit=[{}]", timeout, unit);

        final List<T> results = new CopyOnWriteArrayList<>();

        try {
            for (final Future<T> task : tasks) {
                results.add(task.get(timeout, unit));
            }
        } catch (Exception e) {
            log.error("?    ?.", e);
            throw new RuntimeException(e);
        }
        return results;
    }

    /**
     *  {@link java.util.concurrent.Future}? {@link java.util.concurrent.Future#isDone()}
     * ? {@link java.util.concurrent.Future#isCancelled()}  ?  .
     *
     * @param futures futures
     * @param <T>      
     * @throws InterruptedException
     */
    public static <T> void waitAll(final Iterable<? extends Future<T>> futures) throws InterruptedException {
        boolean allCompleted = false;

        while (!allCompleted) {
            allCompleted = Iterables.all(futures, new Predicate<Future<?>>() {
                @Override
                public boolean apply(Future<?> input) {
                    assert input != null;
                    return input.isDone() || input.isCancelled();
                }
            });
            if (!allCompleted)
                Thread.sleep(1);
        }
    }

    /**
     *  {@link java.util.concurrent.FutureTask}? {@link java.util.concurrent.Future#isDone()}
     * ? {@link java.util.concurrent.Future#isCancelled()}  ?  .
     *
     * @param futureTasks futures
     */
    public static <T> void waitAllTasks(final Iterable<? extends Future<T>> futureTasks)
            throws InterruptedException {
        boolean allCompleted = false;

        while (!allCompleted) {
            allCompleted = Iterables.all(futureTasks, new Predicate<Future<T>>() {
                @Override
                public boolean apply(Future<T> input) {
                    assert input != null;
                    return (input.isDone() || input.isCancelled());
                }
            });

            if (!allCompleted)
                Thread.sleep(1);
        }
    }
}