Understanding Callable vs Runnable: When Futures Block and How to Avoid It
This article compares Java's Callable and Runnable interfaces, demonstrates how Future.get() blocks, shows alternative submit methods, and provides complete code examples illustrating return values, task completion checks, and practical usage of ThreadPoolExecutor.
Java provides two primary interfaces for defining tasks that can be executed by a thread pool: Callable and Runnable . The main advantage of Callable is that it can return a result through a Future, whereas Runnable cannot.
Callable Example and Blocking Behavior
public class MyCallable implements Callable<String> {
private int age;
public MyCallable(int age) {
this.age = age;
}
@Override
public String call() throws Exception {
TimeUnit.SECONDS.sleep(8);
return "返回值 年龄是:" + age;
}
public static void main(String[] args) {
MyCallable myCallable = new MyCallable(22);
int corePoolSize = 2;
int maximumPoolSize = 3;
int keepAliveTime = 5;
TimeUnit unit = TimeUnit.SECONDS;
LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>();
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
Future<String> future = threadPoolExecutor.submit(myCallable);
try {
System.out.println(System.currentTimeMillis());
String string = future.get(); // blocks until callable finishes
System.out.println(string);
System.out.println(System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}The printed timestamps show that future.get() blocks for about eight seconds, confirming its blocking nature.
Submitting a Runnable and Checking Completion
public class Run {
public static void main(String[] args) {
try {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("打印的信息");
}
};
ExecutorService executorService = Executors.newCachedThreadPool();
Future<?> future = executorService.submit(runnable);
System.out.println(future.get() + " " + future.isDone());
} catch (Exception e) {
e.printStackTrace();
}
}
}The output is:
打印的信息
null trueHere future.get() returns null because the runnable has no result, and future.isDone() shows the task completed without blocking.
Using submit(Runnable, T result) to Obtain a Custom Result
public class User {
private String username;
private String password;
// getters and setters omitted
}
public class MyRunnable implements Runnable {
private User user;
public MyRunnable(User user) {
this.user = user;
}
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
user.setUsername("admin");
user.setPassword("123456");
}
}
public class Main {
public static void main(String[] args) {
try {
User user = new User();
MyRunnable myRunnable = new MyRunnable(user);
int corePoolSize = 10;
int maximumPoolSize = 10;
int keepAliveTime = 10;
TimeUnit unit = TimeUnit.SECONDS;
LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
Future<User> future = executor.submit(myRunnable, user);
System.out.println(System.currentTimeMillis());
System.out.println(user.getUsername() + "-" + user.getPassword()); // prints null-null before task finishes
user = future.get(); // blocks until runnable finishes
System.out.println(user.getUsername() + "-" + user.getPassword()); // prints admin-123456
System.out.println(System.currentTimeMillis());
} catch (Exception e) {
e.printStackTrace();
}
}
}The console output demonstrates that before the task completes the user fields are null, and after future.get() they contain the values set inside the runnable, confirming that submit(Runnable, result) can return a custom object.
Overall, Callable is suitable when a task needs to produce a result, but its Future.get() call blocks until completion. Runnable can be submitted with or without a result, and methods like isDone() allow non‑blocking status checks.
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.
