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 * https://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 * @param <T> the type of the object managed by this initializer class 065 * @since 3.0 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 <strong>null</strong>). 076 * @throws IllegalArgumentException if the {@link Callable} is <strong>null</strong>. 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 initializes it with the {@link Callable} to be executed in a background thread and 085 * the {@link ExecutorService} for managing the background execution. 086 * 087 * @param call the {@link Callable} (must not be <strong>null</strong>). 088 * @param exec an external {@link ExecutorService} to be used for task execution. 089 * @throws IllegalArgumentException if the {@link Callable} is <strong>null</strong>. 090 */ 091 public CallableBackgroundInitializer(final Callable<T> call, final ExecutorService exec) { 092 super(exec); 093 checkCallable(call); 094 callable = call; 095 } 096 097 /** 098 * Tests the passed in {@link Callable} and throws an exception if it is undefined. 099 * 100 * @param callable the object to check. 101 * @throws IllegalArgumentException if the {@link Callable} is <strong>null</strong>. 102 */ 103 private void checkCallable(final Callable<T> callable) { 104 Objects.requireNonNull(callable, "callable"); 105 } 106 107 /** 108 * {@inheritDoc} 109 */ 110 @Override 111 protected Exception getTypedException(final Exception e) { 112 //This Exception object will be used for type comparison in AbstractConcurrentInitializer.initialize but not thrown 113 return new Exception(e); 114 } 115 116 /** 117 * Performs initialization in a background thread. This implementation delegates to the {@link Callable} passed at construction time of this object. 118 * 119 * @return the result of the initialization. 120 * @throws Exception if an error occurs. 121 */ 122 @Override 123 protected T initialize() throws Exception { 124 return callable.call(); 125 } 126}