001package org.javasimon.callback.async;
002
003import java.util.concurrent.Callable;
004import java.util.concurrent.ExecutorService;
005import java.util.concurrent.ThreadFactory;
006
007/**
008 * This class contains some basic {@link Executor}s.
009 * <ul>
010 * <li>Disabled: does nothing, callable is not called at all.</li>
011 * <li>Sync: callable is called synchronously, using the same thread as caller, result is returned.</li>
012 * <li>Async: callable is called asynchronously, using the different thread as caller, no result is returned.</li>
013 * </ul>
014 *
015 * @author gerald
016 */
017public final class Executors {
018
019        /** Disabled Executor. */
020        public static Executor DISABLED = new Executor() {
021                public Object execute(Callable callable) throws Throwable {
022                        return null;
023                }
024        };
025        /** Synchronous, same thread Executor. */
026        public static Executor SYNC = new Executor() {
027                public Object execute(Callable callable) throws Throwable {
028                        return callable.call();
029                }
030        };
031        /** Single threaded executor service used by default async. */
032        private static ExecutorService ASYNC_EXECUTOR_SERVICE;
033
034        /** Initializes default single threaded executor service. */
035        private static synchronized ExecutorService initAsyncExecutorService() {
036                if (ASYNC_EXECUTOR_SERVICE == null) {
037                        ASYNC_EXECUTOR_SERVICE = java.util.concurrent.Executors.newSingleThreadExecutor(
038                                new ThreadFactory() {
039                                        public Thread newThread(Runnable r) {
040                                                Thread thread = new Thread(r, "javasimon-async");
041                                                thread.setDaemon(true);
042                                                return thread;
043                                        }
044                                });
045                }
046                return ASYNC_EXECUTOR_SERVICE;
047        }
048
049        /** Asynchronous, different thread executor. */
050        private static class AsyncCallbackExecutor<T> implements Executor<T> {
051                /** Used executor service. */
052                private final ExecutorService executorService;
053
054                public AsyncCallbackExecutor(ExecutorService executorService) {
055                        this.executorService = executorService;
056                }
057
058                public T execute(Callable<T> callable) throws Throwable {
059                        executorService.submit(callable);
060                        return null;
061                }
062
063        }
064
065        /** Returns disabled executor. */
066        public static <T> Executor<T> disabled() {
067                return DISABLED;
068        }
069
070        /** Returns synchronous, same thread executor. */
071        public static <T> Executor<T> sync() {
072                return SYNC;
073        }
074
075        /** Returns asynchronous, different thread executor. */
076        public static <T> Executor<T> async(ExecutorService executorService) {
077                return new AsyncCallbackExecutor(executorService);
078        }
079
080        /** Returns asynchronous, different but unique thread executor. */
081        public static <T> Executor<T> async() {
082                return async(initAsyncExecutorService());
083        }
084
085        /** Stops thread used by default async executor. */
086        public static synchronized void shutdownAsync() {
087                if (ASYNC_EXECUTOR_SERVICE != null) {
088                        ASYNC_EXECUTOR_SERVICE.shutdown();
089                }
090        }
091}