Java Future 多线程如何返回结果?
我仍在学习如何在 Java 中使用 Future 和 Callable。 偶然遇到这个问题:
假设我有类:
TaskWorker implements Callable {
public String id;
public TaskWorker(String id) {
this.id = id;
}
public Documents call() trows Exception {
//Assume here, that Search and Doc are my own method to search and retrieve docs
Search search = new Search();
Documents docResult = search.process(id);
//think about documents has getDocs
//docResult.getDocs() will return number of document found from search
return docResult;
}
}
这是主要方法:
public static void main(String[] args) {
//assume here, that I build in request contains many Id
Request request = new Request();
request.process;
ExecutorService service = Executors.newFixedThreadPool(3);
List<Future<Documents>> result = new ArrayList<Future<Documents>>();
for (int i=0;i<request.length;i++) {
Callable<Documents> worker = new TaskWorker(request.getId[i]);
Future<Documents> submit = executor.submit(worker);
result.add(submit);
}
Response response = new Response();
ArrayList<Documents> docList = new ArrayList<Documents>();
for (Future<Documents> future:result) {
docList.add(future.get().getDocs());
}
response.setDocuments(docList);
}
我想做的是,将请求的一部分分解为在单独的线程中运行,因为每个请求 Id 都是单独的搜索进程。 所以我尝试通过将结果存储在 future 对象中来利用 Java 池。
我感到困惑的是,在这种情况下未来将如何运作? 对于每个线程完成,它会保存结果吗?在所有过程完成后,我可以循环 future 对象以获得正确的结果吗?
另外,不能保证进程会按顺序运行(1、2、3、4 等),对吧? 如果是这样,那么如果我想将每个原始请求与未来结果相关联,最好的策略是什么?
请指教。
谢谢
I am still learning about using Future and Callable in Java.
Stumble into this question:
Say I have class:
TaskWorker implements Callable {
public String id;
public TaskWorker(String id) {
this.id = id;
}
public Documents call() trows Exception {
//Assume here, that Search and Doc are my own method to search and retrieve docs
Search search = new Search();
Documents docResult = search.process(id);
//think about documents has getDocs
//docResult.getDocs() will return number of document found from search
return docResult;
}
}
And here is the main method:
public static void main(String[] args) {
//assume here, that I build in request contains many Id
Request request = new Request();
request.process;
ExecutorService service = Executors.newFixedThreadPool(3);
List<Future<Documents>> result = new ArrayList<Future<Documents>>();
for (int i=0;i<request.length;i++) {
Callable<Documents> worker = new TaskWorker(request.getId[i]);
Future<Documents> submit = executor.submit(worker);
result.add(submit);
}
Response response = new Response();
ArrayList<Documents> docList = new ArrayList<Documents>();
for (Future<Documents> future:result) {
docList.add(future.get().getDocs());
}
response.setDocuments(docList);
}
What I am trying to do is, breaking a part the request to run in separate thread since each of the request Id is separate Search process.
So I am trying to utilize Java pooling, by storing the result in the future object.
The thing I am confused is, how does future will work in this case?
For each thread completion, is it going to hold the results? And after all the process finish, I can just loop future object to get the results right?
Also, there is no guarantee that process will run in order (1,2,3,4,etc), right?
If that the case, then what is the best strategy if I want to associate each original request with the future result?
Please advise.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您无法知道后台线程启动和完成的顺序,但是当您循环遍历 result-ArrayList 时,您当然会按照提交的顺序获得结果。这里唯一可能发生的事情是 .get() 将阻塞,直到该未来对象的特定结果可用(如果尚未可用)。
You cannot know the order in which the background threads are started and finished, but when you loop through your result-ArrayList you will get, of course, the results in the order you submitted them. The only thing that can happen here is that the .get() will block until the particular result of this future-object is available, if not already available.
您应该创建 SynchronizedMap 并将其与请求一起传递给构造函数中的 TaskWorker。 TaskWorker 完成作业后应将 Request 和 Result 添加到映射中。
您不必循环 Futures 来获取结果,只需确保所有作业都已完成即可。
You should create SynchronizedMap and pass it to TaskWorker in constructor together with a Request. TaskWorker should add Request and Result to the map when it finishes the job.
You dont have to loop Futures to get results, just make sure all jobs are finished.