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.concurrent.Callable;
20  import java.util.concurrent.ExecutorService;
21  
22  /**
23   * <p>
24   * A specialized {@link BackgroundInitializer} implementation that wraps a
25   * {@code Callable} object.
26   * </p>
27   * <p>
28   * An instance of this class is initialized with a {@code Callable} object when
29   * it is constructed. The implementation of the {@link #initialize()} method
30   * defined in the super class delegates to this {@code Callable} so that the
31   * {@code Callable} is executed in the background thread.
32   * </p>
33   * <p>
34   * The {@code 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   * {@code Callable} object to be executed, then call the initializer's
43   * {@link #start()} method. This causes the {@code Callable} to be executed in
44   * another thread. When the results of the {@code 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>
51   * // a Callable that performs a complex computation
52   * Callable&lt;Integer&gt; computationCallable = new MyComputationCallable();
53   * // setup the background initializer
54   * CallableBackgroundInitializer&lt;Integer&gt; 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   * </pre>
62   *
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 {@code CallableBackgroundInitializer} and sets
73       * the {@code Callable} to be executed in a background thread.
74       *
75       * @param call the {@code Callable} (must not be <b>null</b>)
76       * @throws IllegalArgumentException if the {@code 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 {@code CallableBackgroundInitializer} and
85       * initializes it with the {@code Callable} to be executed in a background
86       * thread and the {@code ExecutorService} for managing the background
87       * execution.
88       *
89       * @param call the {@code Callable} (must not be <b>null</b>)
90       * @param exec an external {@code ExecutorService} to be used for task
91       * execution
92       * @throws IllegalArgumentException if the {@code 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      * 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(final Callable<T> call) {
121         if (call == null) {
122             throw new IllegalArgumentException("Callable must not be null!");
123         }
124     }
125 }