简单的直接答案是,如果你想使用一个 Callable 来创建和运行后台线程,当然,如果你想获得一个 Future 对象或 Future 的集合,你需要使用 ExecutorService。如果没有 Future,您将无法轻松获取从 Callable 返回的结果,也无法轻松捕获生成的异常。当然,你可以尝试将你的 Callable 包装在 Runnable 中,然后在 Thread 中运行它,但这会引出一个问题,因为这样做会给你带来很多损失。
编辑
您在评论中询问,
你的意思是像下面的代码一样,它的工作原理?
public class Application2 {
public static class WordLengthCallable implements Callable {
public static int count = 0;
private final int numberOfThread = count++;
public Integer call() throws InterruptedException {
int sum = 0;
for (int i = 0; i < 100000; i++) {
sum += i;
}
System.out.println(numberOfThread);
return numberOfThread;
}
}
public static void main(String[] args) throws InterruptedException {
new Thread(new MyRunnable()).start();
new Thread(new MyRunnable()).start();
new Thread(new MyRunnable()).start();
new Thread(new MyRunnable()).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.exit(0);
}
public static class MyRunnable implements Runnable {
@Override
public void run() {
try {
new WordLengthCallable().call();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
我的回答是:是的。链接“排序”中的代码有效。是的,它会创建后台线程,但将丢弃在可调用文件中执行的计算结果,并忽略所有异常。这就是我所说的“因为这样做你会失去很多”。
例如,
ExecutorService execService = Executors.newFixedThreadPool(THREAD_COUNT);
List<Future<Integer>> futures = new ArrayList<>();
for (int i = 0; i < THREAD_COUNT; i++) {
futures.add(execService.submit(new WordLengthCallable()));
}
for (Future<Integer> future : futures) {
try {
System.out.println("Future result: " + future.get());
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Thread.sleep(1000);
System.out.println("done!");
execService.shutdown();
编辑 2
或者,如果您希望在结果发生时返回结果,请使用 CompletionService 来包装您的 ExecutorService,这是我以前从未尝试过的:
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CompletionServiceExample {
public static class WordLengthCallable implements Callable<Integer> {
private Random random = new Random();
public Integer call() throws InterruptedException {
int sleepTime = (2 + random.nextInt(16)) * 500;
Thread.sleep(sleepTime);
return sleepTime;
}
}
private static final int THREAD_COUNT = 4;
public static void main(String[] args) throws InterruptedException {
ExecutorService execService = Executors.newFixedThreadPool(THREAD_COUNT);
CompletionService<Integer> completionService = new ExecutorCompletionService<>(
execService);
for (int i = 0; i < THREAD_COUNT; i++) {
completionService.submit(new WordLengthCallable());
}
execService.shutdown();
try {
while (!execService.isTerminated()) {
int result = completionService.take().get().intValue();
System.out.println("Result is: " + result);
}
} catch (ExecutionException e) {
e.printStackTrace();
}
Thread.sleep(1000);
System.out.println("done!");
}
}