带有返回值的java并发方法调用

时间:2015-07-24 00:27:19

标签: java multithreading concurrency callable executor

我之前发布过有关此主题的内容,但我认为我误解了并发处理的工作原理。我本质上有一个带有收集数据的对象的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()返回。我假设这个实现是不正确的,这个功能的正确实现是什么?感谢。

3 个答案:

答案 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();