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 */ 017package org.apache.commons.lang3.concurrent; 018 019import java.util.Objects; 020import java.util.concurrent.Callable; 021import java.util.concurrent.ExecutorService; 022 023/** 024 * A specialized {@link BackgroundInitializer} implementation that wraps a 025 * {@link Callable} object. 026 * 027 * <p> 028 * An instance of this class is initialized with a {@link Callable} object when 029 * it is constructed. The implementation of the {@link #initialize()} method 030 * defined in the super class delegates to this {@link Callable} so that the 031 * {@link 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 * {@link Callable} object to be executed, then call the initializer's 043 * {@link #start()} method. This causes the {@link Callable} to be executed in 044 * another thread. When the results of the {@link 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 * </p> 049 * 050 * <pre> 051 * // a Callable that performs a complex computation 052 * Callable<Integer> computationCallable = new MyComputationCallable(); 053 * // setup the background initializer 054 * CallableBackgroundInitializer<Integer> initializer = 055 * new CallableBackgroundInitializer(computationCallable); 056 * initializer.start(); 057 * // Now do some other things. Initialization runs in a parallel thread 058 * ... 059 * // Wait for the end of initialization and access the result 060 * Integer result = initializer.get(); 061 * </pre> 062 * 063 * @since 3.0 064 * @param <T> the type of the object managed by this initializer class 065 */ 066public class CallableBackgroundInitializer<T> extends BackgroundInitializer<T> { 067 /** The Callable to be executed. */ 068 private final Callable<T> callable; 069 070 /** 071 * Creates a new instance of {@link CallableBackgroundInitializer} and sets 072 * the {@link Callable} to be executed in a background thread. 073 * 074 * @param call the {@link Callable} (must not be <b>null</b>) 075 * @throws IllegalArgumentException if the {@link Callable} is <b>null</b> 076 */ 077 public CallableBackgroundInitializer(final Callable<T> call) { 078 checkCallable(call); 079 callable = call; 080 } 081 082 /** 083 * Creates a new instance of {@link CallableBackgroundInitializer} and 084 * initializes it with the {@link Callable} to be executed in a background 085 * thread and the {@link ExecutorService} for managing the background 086 * execution. 087 * 088 * @param call the {@link Callable} (must not be <b>null</b>) 089 * @param exec an external {@link ExecutorService} to be used for task 090 * execution 091 * @throws IllegalArgumentException if the {@link Callable} is <b>null</b> 092 */ 093 public CallableBackgroundInitializer(final Callable<T> call, final ExecutorService exec) { 094 super(exec); 095 checkCallable(call); 096 callable = call; 097 } 098 099 /** 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}