我已经为一个简单的迷宫项目工作了一段时间,我到了需要使用Callable接口作为线程的地步。在实现和运行之后,我注意到当可调用类在后台运行时,我似乎无法在后台运行任何其他内容,例如输入。
我做了一个强调问题的小项目,看到当可调用类工作10秒时,我不能同时接受任何输入。 这是代码:
主要课程
public class Main {
static ExecutorService service = null;
static Future<String> task = null;
public static void main(final String[] argv) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("please enter a command");
String string = in.readLine();
while (!string.equals("exit")) {
if (!string.equals("command")) {
System.out.println("command not found");
} else {
service = Executors.newFixedThreadPool(1);
task = service.submit(new Foo());
try {
final String str;
// waits the 10 seconds for the Callable.call to finish.
str = task.get(); // this raises ExecutionException if
// thread dies
System.out.println(str);
service.shutdownNow();
} catch (final InterruptedException ex) {
ex.printStackTrace();
} catch (final ExecutionException ex) {
ex.printStackTrace();
}
}
string = in.readLine();
}
//
}
}
可调用类:
class Foo implements Callable<String> {
@Override
public String call() {
try {
// sleep for 10 seconds
Thread.sleep(10 * 1000);
} catch (final InterruptedException ex) {
ex.printStackTrace();
}
return ("Hello, World!");
}
}
答案 0 :(得分:3)
如果您想立即阻止等待任务,可以使用结构形式为result = exec.submit(aCallable).get();
这正是你正在做的事情(阻止等待任务的主线程)
答案 1 :(得分:2)
问题是str = task.get();
。
根据JavaDoc for Future#get()(https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get%28%29):
如果需要等待计算完成,然后检索其结果。
如果你想要Callable的结果,你必须等到它完成。
答案 2 :(得分:1)
Callable并不做任何事情。它只是一个约定界面。要使可调用异步,您需要在执行程序中运行它。例如,请参阅https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6。
答案 3 :(得分:1)
我注意到,当可调用类在后台运行时,我似乎无法在后台运行其他任何东西
...讨论,......问题解释......
现在使用这个界面似乎毫无意义。
我真的不知道你要做什么,但ExecutorService
和Callable
的重点是在后台执行任务。
但是&#34;在背景中是什么&#34;意思?这意味着,当新线程执行某项任务时,提交任务的线程可以执行其他操作。
看起来像这样:
final ExecutorService executorService = Executors.newFixedThreadPool(NUM_THREADS);
ReturnType doSomethingInTheBackground() {
// create the task object
Callable<ReturnType> task = () -> doSomething();
// submit the task object
Future<ReturnType> future = executorService.submit(task);
doSomethingElse();
// wait for the result.
return future.get();
}
private ReturnType doSomething() { ... }
private void doSomethingElse() { ... }
doSomethingElse()
电话是值得的。如果调用线程除了等待结果之外没有其他任何事情要做(即调用future.get()
),那么你是对的:使用多个线程是没有意义的。调用线程只是自己执行任务会更简单。