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 {@link 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>{@code 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 * } 062 * </pre> 063 * 064 * @since 3.0 065 * @param <T> the type of the object managed by this initializer class 066 */ 067public class CallableBackgroundInitializer<T> extends BackgroundInitializer<T> { 068 /** The Callable to be executed. */ 069 private final Callable<T> callable; 070 071 /** 072 * Creates a new instance of {@link CallableBackgroundInitializer} and sets 073 * the {@link Callable} to be executed in a background thread. 074 * 075 * @param call the {@link Callable} (must not be <b>null</b>) 076 * @throws IllegalArgumentException if the {@link Callable} is <b>null</b> 077 */ 078 public CallableBackgroundInitializer(final Callable<T> call) { 079 checkCallable(call); 080 callable = call; 081 } 082 083 /** 084 * Creates a new instance of {@link CallableBackgroundInitializer} and 085 * initializes it with the {@link Callable} to be executed in a background 086 * thread and the {@link ExecutorService} for managing the background 087 * execution. 088 * 089 * @param call the {@link Callable} (must not be <b>null</b>) 090 * @param exec an external {@link ExecutorService} to be used for task 091 * execution 092 * @throws IllegalArgumentException if the {@link Callable} is <b>null</b> 093 */ 094 public CallableBackgroundInitializer(final Callable<T> call, final ExecutorService exec) { 095 super(exec); 096 checkCallable(call); 097 callable = call; 098 } 099 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}