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 {@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   * {@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>
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   * @since 3.0
64   * @param <T> the type of the object managed by this initializer class
65   */
66  public class CallableBackgroundInitializer<T> extends BackgroundInitializer<T> {
67      /** The Callable to be executed. */
68      private final Callable<T> callable;
69  
70      /**
71       * Creates a new instance of {@link CallableBackgroundInitializer} and sets
72       * the {@link Callable} to be executed in a background thread.
73       *
74       * @param call the {@link Callable} (must not be <b>null</b>)
75       * @throws IllegalArgumentException if the {@link Callable} is <b>null</b>
76       */
77      public CallableBackgroundInitializer(final Callable<T> call) {
78          checkCallable(call);
79          callable = call;
80      }
81  
82      /**
83       * Creates a new instance of {@link CallableBackgroundInitializer} and
84       * initializes it with the {@link Callable} to be executed in a background
85       * thread and the {@link ExecutorService} for managing the background
86       * execution.
87       *
88       * @param call the {@link Callable} (must not be <b>null</b>)
89       * @param exec an external {@link ExecutorService} to be used for task
90       * execution
91       * @throws IllegalArgumentException if the {@link Callable} is <b>null</b>
92       */
93      public CallableBackgroundInitializer(final Callable<T> call, final ExecutorService exec) {
94          super(exec);
95          checkCallable(call);
96          callable = call;
97      }
98  
99      /**
100      * Tests the passed in {@link Callable} and throws an exception if it is
101      * undefined.
102      *
103      * @param callable the object to check
104      * @throws IllegalArgumentException if the {@link Callable} is <b>null</b>
105      */
106     private void checkCallable(final Callable<T> callable) {
107         Objects.requireNonNull(callable, "callable");
108     }
109 
110     /**
111      * {@inheritDoc}
112      */
113     @Override
114     protected Exception getTypedException(Exception e) {
115         //This Exception object will be used for type comparison in AbstractConcurrentInitializer.initialize but not thrown
116         return new Exception(e);
117     }
118 
119     /**
120      * Performs initialization in a background thread. This implementation
121      * delegates to the {@link Callable} passed at construction time of this
122      * object.
123      *
124      * @return the result of the initialization
125      * @throws Exception if an error occurs
126      */
127     @Override
128     protected T initialize() throws Exception {
129         return callable.call();
130     }
131 }