我之前发布过有关此主题的内容,但我认为我误解了并发处理的工作原理。我本质上有一个带有收集数据的对象的servlet,每当客户端连接时,我希望能够调用一个方法来同时检索数据。我尝试了以下代码:
public class Test {
private ExecutorService exec = Executors.newFixedThreadPool(10);
public Thing getStuff(){
class Getter implements Callable<Thing>{
public Thing call(){
//do collection stuff
return Thing;
}
}
Callable<Thing> callable = new Getter();
Future<Thing> future = exec.submit(callable);
return future.get();
}
}
当我尝试检索可调用的结果时,我必须使用.get()来防止后续调用.getStuff()返回。我假设这个实现是不正确的,这个功能的正确实现是什么?感谢。
答案 0 :(得分:0)
这是正确的并且将同时运行(最多10个并发,因为你的线程池有多大)。
这不会同时运行的唯一原因是你在call()方法中(或者在那个方法中调用的方法)中进行了一些同步。
您的测试方法可能不正确并且只在一个线程中运行吗?如果您的测试如下:
Test t = new Test();
while (true) {
t.getStuff();
}
然后它一次只运行一个getStuff实例,因为你的测试是单线程的,而不是因为你的服务器。
答案 1 :(得分:0)
嗯,在它存在之前你不能有任何Thing
。因此,当通过Thing
请求生成的get
实例时,获取它的唯一方法是等待异步操作的完成,以便能够返回Callable
返回的内容。 / p>
解决这个问题的唯一方法就是不调用get
,这意味着您无法返回Thing
实例,因为它可能不完整甚至当时不存在{{1}方法返回。否则,它不是一个异步操作。
因此,调用者也必须处理操作的异步性质。或者,getStuff()
返回表示正在进行的操作的getStuff()
,或者调用者将通过参数对象处理结果的代码传递给Future
,因此它也可以异步执行。 / p>
简单地说,异步处理的整个想法是在异步操作运行时能够做其他事情。如果在您的应用程序中,您所能做的就是等待操作的结果,那么异步执行就没有意义。
答案 2 :(得分:0)
您的示例中的此代码段将新的Getter
任务提交到池线程,然后立即等待池线程完成任务:
Callable<Thing> callable = new Getter();
Future<Thing> future = exec.submit(callable);
return future.get();
那是什么意思?为什么不在当前线程中执行Getter
任务:
return new Getter().call();
将任务提供给池线程的全部意义在于,当池线程正在工作时,当前线程可以执行其他操作。
Callable<Thing> callable = new Getter();
Future<Thing> future = exec.submit(callable);
doSomethingElseThatTakesAWhile();
return future.get();