Boost Java API Performance with ThreadPool and FutureTask: A Practical Guide
This article explains how to use a thread pool together with FutureTask to split a large query into many small asynchronous tasks, improving response speed and handling exceptions correctly in Java concurrent programming.
Previously the API for querying red packet rights timed out because many user‑purchased rights were involved.
Solution
Use a thread pool combined with FutureTask to split one large query into many small queries. FutureTask is chosen because its run() method executes only once, preventing duplicate queries, and asynchronous multi‑task execution improves response speed.
This article demonstrates an example of using a thread pool with FutureTask for asynchronous execution.
ThreadPool + FutureTask for Multi‑Task Computation
public class Test {
// Thread pool should be a global variable; if local, remember to shutdown() after use
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("thread-start-runner-%d").build();
ExecutorService taskExe = new ThreadPoolExecutor(10, 20, 800L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(100), namedThreadFactory);
int count = 0;
@Test
public void test(String[] args) {
// Task list
List<FutureTask<Integer>> taskList = new ArrayList<FutureTask<Integer>>();
for (int i = 0; i < 100; i++) {
// Create 100 tasks and put them into the task list
FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 1;
}
});
// The execution result is stored back into the original FutureTask; later we can iterate taskList to get results
taskList.add(futureTask);
taskExe.submit(futureTask);
}
// Get results
try {
for (FutureTask<Integer> futureTask : taskList) {
count += futureTask.get();
}
} catch (InterruptedException e) {
logger.error("Thread execution was interrupted", e);
} catch (ExecutionException e) {
logger.error("Thread execution encountered an exception", e);
}
// Shut down the thread pool
taskExe.shutdown();
// Print: 100
System.out.println(count);
}
}The Callable interface lets us obtain the thread’s execution result, so it is used as the argument of FutureTask(Callable<V> callable).
FutureTask stores the result in its private outcome field; other threads can read it via futureTask.get().
Exceptions in Sub‑threads That Cannot Be Propagated
Submitting a task with submit(Runnable task) has a hidden risk:
FutureTask’s internal run() block catches exceptions and assigns them to the outcome object via setException(Throwable t). If you never call FutureTask.get(), the exception is swallowed and the sub‑thread may stop silently.
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
// Create an asynchronous task FutureTask, the risk is also inside its run() block
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}In the example above, because FutureTask.get() is called, any exception will be retrieved.
Source: https://blog.csdn.net/qq_44384533/article/details/112324224
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
