我有一个公共方法,在其中我使用executor框架来创建多个线程,并且所有线程都访问同一个私有方法。
以下代码:
public String getValue(Map map1, Map map2, Map map3, Map map4) {
ExecutorService es = Executors.newFixedThreadPool(4);
CompletionService<Object> cs = new ExecutorCompletionService<Object>(es);
cs.submit(new Callable<Object>() {
public Object call() throws Exception {
getCount(map1);
return null;
}
});
cs.submit(new Callable<Object>() {
public Object call() throws Exception {
getCount(map2);
return null;
}
});
cs.submit(new Callable<Object>() {
public Object call() throws Exception {
getCount(map2);
return null;
}
});
cs.submit(new Callable<Object>() {
public Object call() throws Exception {
getCount(map3);
return null;
}
});
for (int i = 0; i < 4; i++) {
try {
cs.take().get(); // find the first completed task
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
}
}
private int getCount(final Map map) {
List<String> list = new ArrayList<>();
for (Map.Entry<> elem : map.entrySet()) {
list.add(elem .getValue()) ;
}
int count = 0;
for(String fields: list){
count + = // Some time consuming DB operation
}
return count;
}
私有方法中声明的变量的值会有任何混淆吗?或者会有任何Hashmap迭代问题吗?
如何调用私有方法?不同线程是否有多个私有方法的副本,或者所有线程将同时执行该私有方法。
如果你觉得这个问题有点愚蠢,请耐心等待:)
如果您询问方法参数和方法内部变量,答案是否定的。这些变量在堆栈上分配,每个线程都不同。
编辑:当传递共享(在多个线程之间)非线程安全对象时,可能会出现问题。例如,您的方法foo()
接受类型为MyClass
:的参数
foo(MyClass param) {}
在foo()
的某个地方,您可以调用param.bar()
,它(直接或间接)使用非线程安全的成员变量进行操作。在这种情况下,您将获得比赛条件。
(感谢@dictionre)
然而,线程同步问题与类字段相关。
您的代码应该不会有任何问题,因为您没有操作parameters
(例如,映射中的adding/removing
内容)。
当然,有这样的假设,即这些映射是不相关的(例如sharing same resources
)和在程序中的其他地方,您将在运行该方法的同时操作这些对象。
是的,我的解释可能会让读者头疼。但根据使用map
和multi-threaded programming
的经验,可能会出现大量其他问题。
因此,尽管你非常确信不会出任何问题,但还是要给你一句建议,尽量让你的程序成为thread-safe
。