我不确定我能否以最清晰的方式提出问题,但我会尽我所能。
让我们说我正在从第三方api中检索一些信息。检索到的信息将是巨大的。为了获得性能提升,而不是一次性检索所有信息,我将以分页的方式检索信息(api给了我那个设施,基本上是一个迭代器)。返回类型基本上是一个对象列表。
我的目标是处理我手头的信息(包括在db和许多其他操作中进行比较和存储),同时我获得请求的分页响应。
我对专家社区的问题是,在这种情况下,您更喜欢哪种数据结构。像弹簧批处理这样的框架也可以帮助您在这种情况下获得性能提升。
我知道这个问题有点模糊,但我正在寻找一般的想法,提示和指示。
答案 0 :(得分:0)
就实际并行性而言,Java中一个非常有用的构造是ThreadPoolExecutor
。这可能是什么样子的粗略草图:
public class YourApp {
class Processor implements Runnable {
Widget toProcess;
public Processor(Widget toProcess) {
this.toProcess = toProcess;
}
public void run() {
// commit the Widget to the DB, etc
}
}
public static void main(String[] args) {
ThreadPoolExecutor executor =
new ThreadPoolExecutor(1, 10, 30,
TimeUnit.SECONDS,
new LinkedBlockingDeque());
while(thereAreStillWidgets()) {
ArrayList<Widget> widgets = doExpensiveDatabaseCall();
for(Widget widget : widgets) {
Processor procesor = new Processor(widget);
executor.execute(processor);
}
}
}
}
但正如我在评论中所说:对外部API的调用昂贵。很可能最好的策略是在一次调用中从API中提取所有Widget
个对象,然后在获得它们后并行处理它们。进行更多的API调用会让您每次都从服务器向您发送数据的开销 - 您可能最好以最少的次数支付该费用。
另外,请记住,如果您正在进行数据库操作,那么您的数据库可能不允许并行写入,因此您可能会在那里放慢速度。
答案 1 :(得分:0)
在这些情况下,我的数据结构是java.util.concurrent.CompletionService。
出于示例的目的,我将假设一些额外的约束:
这里是:
// a class that knows how to update the DB given a page of results
class DatabaseUpdater implements Callable { ... }
// a background thread to do the work
final CompletionService<Object> exec = new ExecutorCompletionService(
Executors.newSingleThreadExecutor());
// first call
List<Object> results = ThirdPartyAPI.getPage( ... );
// Start loading those results to DB on background thread
exec.submit(new DatabaseUpdater(results));
while( you need to ) {
// Another call to remote service
List<Object> results = ThirdPartyAPI.getPage( ... );
// wait for existing work to complete
exec.take();
// send more work to background thread
exec.submit(new DatabaseUpdater(results));
}
// wait for the last task to complete
exec.take();
这只是一个简单的双线程设计。第一个线程负责从远程服务获取数据,第二个线程负责写入数据库。
在获取结果时(通过exec.take()
),DatabaseUpdater抛出的任何异常都将传播到主线程。