我正在尝试使用批处理操作从facebook获取帖子。 我想让这个任务多线程以加快操作。 基本上,我发送批处理请求到Facebook,并在等待响应时,我的任务是做其他需要完成的事情。 当我调试任务(慢慢地)我得到了2000个结果我想得到测试.... 但是当我运行它或让它在请求操作之后进行调试和暂停时,它会小于2000。
String[] str = new String[2000];
ExecutorService exec = Executors.newFixedThreadPool(10);
List<BatchRequest> request= new CopyOnWriteArrayList<BatchRequest>();
List <BatchResponse> batchResponses = new ArrayList<BatchResponse>();
int i=1;
for(int j=0 ; j<2000; j++) {
if (i < 50) {
BatchRequest batch = new BatchRequestBuilder(str[i]).build();
request.add(batch);
i++;
counter++;
} else {
i = 1;
exec.execute(new Runnable() {
//thread that gets information from facebook into a list of responses
public void run() {
// TODO Auto-generated method stub
System.out.println("running");
batchResponses.addAll(fc.executeBatch(request));
System.out.println("done");
}
});
request.clear();
}
}
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
我删除了所有不必要的内容。希望它仍然有意义。
我的代码有什么问题?
编辑:我编辑了代码以使其更有意义。任何人吗?
答案 0 :(得分:1)
除了@OldCurmudgeon的回答,我可以说ArrayList
不是线程安全的类。您可以使用其他容器,使用Collections.synchronizedList()
包装它或将同步添加到您的代码中。
还要确保您的fc
变量引用线程安全类。
答案 1 :(得分:0)
您的代码似乎在counter
和i
之间存在一些混淆。也许如果你解释为什么你需要这些东西会变得更清楚。
代码代表的主要问题是你永远不会将counter
设置为零。这将导致前500个在其自己的线程中作为一个批处理执行,但其余的每个都将自行执行。
答案 2 :(得分:0)
一些问题: batchResponses正在线程内部访问,并且您正在主线程中推送它。 batchResponses也不是线程安全的,因此需要同步它。
你也在主线程中做request.clear ...这是bug,因为你不能保证新线程已执行,可能是新线程清除后运行的情况。新线程将看到request.size(0)= 0。
主if块和else块具有相同的线程代码,这有点令人困惑。 if(i == 50)你进入else块并执行请求。 当你的计数器是500时,你已经访问了else块10次,所以你可能有空的请求或你插入的最后50个。
此代码中的某些内容尚不清楚。