    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     * @since 3.0
    065     * @version $Id: CallableBackgroundInitializer.java 1082044 2011-03-16 04:26:58Z bayard $
    066     * @param <T> the type of the object managed by this initializer class
    067     */
    068    public class CallableBackgroundInitializer<T> extends BackgroundInitializer<T> {
    069        /** The Callable to be executed. */
    070        private final Callable<T> callable;
    071
    072        /**
    073         * Creates a new instance of {@code CallableBackgroundInitializer} and sets
    074         * the {@code Callable} to be executed in a background thread.
    075         *
    076         * @param call the {@code Callable} (must not be <b>null</b>)
    077         * @throws IllegalArgumentException if the {@code Callable} is <b>null</b>
    078         */
    079        public CallableBackgroundInitializer(Callable<T> call) {
    080            checkCallable(call);
    081            callable = call;
    082        }
    083
    084        /**
    085         * Creates a new instance of {@code CallableBackgroundInitializer} and
    086         * initializes it with the {@code Callable} to be executed in a background
    087         * thread and the {@code ExecutorService} for managing the background
    088         * execution.
    089         *
    090         * @param call the {@code Callable} (must not be <b>null</b>)
    091         * @param exec an external {@code ExecutorService} to be used for task
    092         * execution
    093         * @throws IllegalArgumentException if the {@code Callable} is <b>null</b>
    094         */
    095        public CallableBackgroundInitializer(Callable<T> call, ExecutorService exec) {
    096            super(exec);
    097            checkCallable(call);
    098            callable = call;
    099        }
    100
    101        /**
    102         * Performs initialization in a background thread. This implementation
    103         * delegates to the {@code Callable} passed at construction time of this
    104         * object.
    105         *
    106         * @return the result of the initialization
    107         * @throws Exception if an error occurs
    108         */
    109        @Override
    110        protected T initialize() throws Exception {
    111            return callable.call();
    112        }
    113
    114        /**
    115         * Tests the passed in {@code Callable} and throws an exception if it is
    116         * undefined.
    117         *
    118         * @param call the object to check
    119         * @throws IllegalArgumentException if the {@code Callable} is <b>null</b>
    120         */
    121        private void checkCallable(Callable<T> call) {
    122            if (call == null) {
    123                throw new IllegalArgumentException("Callable must not be null!");
    124            }
    125        }
    126    }