View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.concurrent;
18  
19  import java.util.Objects;
20  import java.util.concurrent.Callable;
21  import java.util.concurrent.ExecutorService;
22  
23  /**
24   * A specialized {@link BackgroundInitializer} implementation that wraps a
25   * {@link Callable} object.
26   *
27   * <p>
28   * An instance of this class is initialized with a {@link Callable} object when
29   * it is constructed. The implementation of the {@link #initialize()} method
30   * defined in the super class delegates to this {@link Callable} so that the
31   * {@link Callable} is executed in the background thread.
32   * </p>
33   * <p>
34   * The {@link java.util.concurrent.Callable} interface is a standard mechanism
35   * of the JDK to define tasks to be executed by another thread. The {@code
36   * CallableBackgroundInitializer} class allows combining this standard interface
37   * with the background initializer API.
38   * </p>
39   * <p>
40   * Usage of this class is very similar to the default usage pattern of the
41   * {@link BackgroundInitializer} class: Just create an instance and provide the
42   * {@link Callable} object to be executed, then call the initializer's
43   * {@link #start()} method. This causes the {@link Callable} to be executed in
44   * another thread. When the results of the {@link Callable} are needed the
45   * initializer's {@link #get()} method can be called (which may block until
46   * background execution is complete). The following code fragment shows a
47   * typical usage example:
48   * </p>
49   *
50   * <pre>{@code
51   * // a Callable that performs a complex computation
52   * Callable<Integer> computationCallable = new MyComputationCallable();
53   * // setup the background initializer
54   * CallableBackgroundInitializer<Integer> initializer =
55   *     new CallableBackgroundInitializer(computationCallable);
56   * initializer.start();
57   * // Now do some other things. Initialization runs in a parallel thread
58   * ...
59   * // Wait for the end of initialization and access the result
60   * Integer result = initializer.get();
61   * }
62   * </pre>
63   *
64   * @since 3.0
65   * @param <T> the type of the object managed by this initializer class
66   */
67  public class CallableBackgroundInitializer<T> extends BackgroundInitializer<T> {
68      /** The Callable to be executed. */
69      private final Callable<T> callable;
70  
71      /**
72       * Creates a new instance of {@link CallableBackgroundInitializer} and sets
73       * the {@link Callable} to be executed in a background thread.
74       *
75       * @param call the {@link Callable} (must not be <b>null</b>)
76       * @throws IllegalArgumentException if the {@link Callable} is <b>null</b>
77       */
78      public CallableBackgroundInitializer(final Callable<T> call) {
79          checkCallable(call);
80          callable = call;
81      }
82  
83      /**
84       * Creates a new instance of {@link CallableBackgroundInitializer} and
85       * initializes it with the {@link Callable} to be executed in a background
86       * thread and the {@link ExecutorService} for managing the background
87       * execution.
88       *
89       * @param call the {@link Callable} (must not be <b>null</b>)
90       * @param exec an external {@link ExecutorService} to be used for task
91       * execution
92       * @throws IllegalArgumentException if the {@link Callable} is <b>null</b>
93       */
94      public CallableBackgroundInitializer(final Callable<T> call, final ExecutorService exec) {
95          super(exec);
96          checkCallable(call);
97          callable = call;
98      }
99  
100     /**
101      * Tests the passed in {@link Callable} and throws an exception if it is
102      * undefined.
103      *
104      * @param callable the object to check
105      * @throws IllegalArgumentException if the {@link Callable} is <b>null</b>
106      */
107     private void checkCallable(final Callable<T> callable) {
108         Objects.requireNonNull(callable, "callable");
109     }
110 
111     /**
112      * {@inheritDoc}
113      */
114     @Override
115     protected Exception getTypedException(final Exception e) {
116         //This Exception object will be used for type comparison in AbstractConcurrentInitializer.initialize but not thrown
117         return new Exception(e);
118     }
119 
120     /**
121      * Performs initialization in a background thread. This implementation
122      * delegates to the {@link Callable} passed at construction time of this
123      * object.
124      *
125      * @return the result of the initialization
126      * @throws Exception if an error occurs
127      */
128     @Override
129     protected T initialize() throws Exception {
130         return callable.call();
131     }
132 }