    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017    package org.apache.commons.lang3.concurrent;
    018
    019    import java.util.concurrent.Callable;
    020    import java.util.concurrent.ExecutorService;
    021
    022    /**
    023     * <p>
    024     * A specialized {@link BackgroundInitializer} implementation that wraps a
    025     * {@code Callable} object.
    026     * </p>
    027     * <p>
    028     * An instance of this class is initialized with a {@code Callable} object when
    029     * it is constructed. The implementation of the {@link #initialize()} method
    030     * defined in the super class delegates to this {@code Callable} so that the
    031     * {@code Callable} is executed in the background thread.
    032     * </p>
    033     * <p>
    034     * The {@code java.util.concurrent.Callable} interface is a standard mechanism
    035     * of the JDK to define tasks to be executed by another thread. The {@code
    036     * CallableBackgroundInitializer} class allows combining this standard interface
    037     * with the background initializer API.
    038     * </p>
    039     * <p>
    040     * Usage of this class is very similar to the default usage pattern of the
    041     * {@link BackgroundInitializer} class: Just create an instance and provide the
    042     * {@code Callable} object to be executed, then call the initializer's
    043     * {@link #start()} method. This causes the {@code Callable} to be executed in
    044     * another thread. When the results of the {@code Callable} are needed the
    045     * initializer's {@link #get()} method can be called (which may block until
    046     * background execution is complete). The following code fragment shows a
    047     * typical usage example:
    048     *
    049     * <pre>
    050     * // a Callable that performs a complex computation
    051     * Callable&lt;Integer&gt; computationCallable = new MyComputationCallable();
    052     * // setup the background initializer
    053     * CallableBackgroundInitializer&lt;Integer&gt; initializer =
    054     *     new CallableBackgroundInitializer(computationCallable);
    055     * initializer.start();
    056     * // Now do some other things. Initialization runs in a parallel thread
    057     * ...
    058     * // Wait for the end of initialization and access the result
    059     * Integer result = initializer.get();
    060     * </pre>
    061     *
    062     * </p>
    063     *
    064     * @version $Id: CallableBackgroundInitializer.java 889215 2009-12-10 11:56:38Z bayard $
    065     * @param <T> the type of the object managed by this initializer class
    066     */
    067    public class CallableBackgroundInitializer<T> extends BackgroundInitializer<T> {
    068        /** The Callable to be executed. */
    069        private final Callable<T> callable;
    070
    071        /**
    072         * Creates a new instance of {@code CallableBackgroundInitializer} and sets
    073         * the {@code Callable} to be executed in a background thread.
    074         *
    075         * @param call the {@code Callable} (must not be <b>null</b>)
    076         * @throws IllegalArgumentException if the {@code Callable} is <b>null</b>
    077         */
    078        public CallableBackgroundInitializer(Callable<T> call) {
    079            checkCallable(call);
    080            callable = call;
    081        }
    082
    083        /**
    084         * Creates a new instance of {@code CallableBackgroundInitializer} and
    085         * initializes it with the {@code Callable} to be executed in a background
    086         * thread and the {@code ExecutorService} for managing the background
    087         * execution.
    088         *
    089         * @param call the {@code Callable} (must not be <b>null</b>)
    090         * @param exec an external {@code ExecutorService} to be used for task
    091         * execution
    092         * @throws IllegalArgumentException if the {@code Callable} is <b>null</b>
    093         */
    094        public CallableBackgroundInitializer(Callable<T> call, ExecutorService exec) {
    095            super(exec);
    096            checkCallable(call);
    097            callable = call;
    098        }
    099
    100        /**
    101         * Performs initialization in a background thread. This implementation
    102         * delegates to the {@code Callable} passed at construction time of this
    103         * object.
    104         *
    105         * @return the result of the initialization
    106         * @throws Exception if an error occurs
    107         */
    108        @Override
    109        protected T initialize() throws Exception {
    110            return callable.call();
    111        }
    112
    113        /**
    114         * Tests the passed in {@code Callable} and throws an exception if it is
    115         * undefined.
    116         *
    117         * @param call the object to check
    118         * @throws IllegalArgumentException if the {@code Callable} is <b>null</b>
    119         */
    120        private void checkCallable(Callable<T> call) {
    121            if (call == null) {
    122                throw new IllegalArgumentException("Callable must not be null!");
    123            }
    124        }
    125    }