我有一个for循环,循环约10亿次。每次迭代中都有许多数据库查询和计算。简化的伪代码如下所示:
for(int i=0, i<1000000000, i++){
query();
if(...){
compute();
}
}
如果我可以并行设置并运行多个线程,那么每个线程都会迭代数百万次,这将大大减少时间。
没有某种并行处理,将需要几个月的时间才能完成。在这种情况下可以通过实施线程来减少时间吗?我知道Java8中的新流功能,但是升级到Java8对我来说不是一个选择。
如果某处有易于遵循的指南,那也很好!预先感谢。
编辑:这是更详细的代码。我可能会针对每次插入多次检查数据库,因此必须先处理数据。理想情况下,我希望多个线程共享工作量。
for(int i = 1; i<=100000000; i++){
String pid = ns.findPId(i); //query
object g = findObject(pid) //query
if(g!=null){
if(g.getSomeProperty()!=null && g.getSomeProperty().matches(EL)){
int isMatch = checkMatch(pid); //query
if(isMatch == 0){
String sampleId = findSampleId(pid); //query
if(sampleId!=null){
Object temp = ns.findMoreProperties(sampleId); //query
if(temp!=null){
g.setSomeAttribute(temp.getSomeAttribute());
g.setSomeOtherProperty(temp.getSomeOtherProperty());
insertObject(g); //compute, encapsulate and insert into database table
}
}
}else{
//log
}
}
}
答案 0 :(得分:1)
1)评估并查看是否需要ThreadPoolExecutor:
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
2)为第一部分写一个Callable
public class FindObjectCallable implements Callable<Object> {
...
@Override
public Object call() throws Exception {
String pid = ns.findPId(i); //query
return findObject(pid) //query
}
}
3)主要代码如下:
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
List<Future<Object>> futures = new ArrayList<Future<Object>>(0);
for(int i = 1; i<=100000000; i++) {
FindObjectCallable callable = new FindObjectCallable( ns, i );
Future<Object> result = executor.submit(callable);
futures.add(result);
}
for( Future<Object> future: futures )
{
// do a java 7 lambda equivalent for the g processing part
}
答案 1 :(得分:0)
似乎您需要的是类似Parallel的东西。 这篇文章以一个实现自己的并行方式的人为例解决了这个问题。在Java中:Parallel.For implemented with Java
我不会使用Dang Nguyen推荐的示例,因为那只是旋转了很多线程,但是因为没有锁定,所以没有线程安全性或适当的并发性。当有两个线程试图同时写入数据库中的同一字段时,您将遇到数据库抛出的异常,这是一个很大的变化。
即使使用并行的for循环,我仍然有机会遇到数据库中的并发问题,因为并行运行的2个线程任务仍可能与访问同一数据库实体有关。