我在Java中遇到多线程问题。我需要将一大串名称与自身进行比较(以找到近似重复的名称)。
我将工作分成4个不同的线程,每个线程将列表的1/4与完整列表进行比较。我为所有4个线程使用相同的类。
当我看到线程监视器时,我发现它们并没有真正同时运行,它们一个接一个地处于活动状态。
可能是什么问题?
这是我的线程类的运行方法:
@Override
public void run() {
try {
s = settings.conn.createStatement();
JaroWinklerDistance jw = JaroWinklerDistance.JARO_WINKLER_DISTANCE;
for (int i = 0; i < names.size(); i++) {
for (int j = 0; j < allNames.size(); j++) {
if (j % 250 == 0) {
}
double proximity = jw.proximity(names.get(i), allNames.get(j));
if (proximity > Double.parseDouble(settings.properties.getProperty("distanceTreshold")) && proximity < 1.00) {
if (names.get(i).length() > allNames.get(j).length()) {
substituteName(allNames.get(j), names.get(i));
allNames.remove(allNames.get(j));
} else {
substituteName(names.get(i), allNames.get(j));
names.remove(names.get(i));
break;
}
}
}
}
} catch (SQLException ex) {
Exceptions.printStackTrace(ex);
}
}
substituteName-method执行更新记录的SQL查询。
线程创建如下:
settings.getAllNames();
int size = settings.allNames.size();
int rest = size % 4;
int groupSize = (size-rest) / 4;
GroupNormalizer a = new GroupNormalizer(settings.allNames, new ArrayList<String>(settings.allNames.subList(0, groupSize)));
GroupNormalizer b = new GroupNormalizer(settings.allNames, new ArrayList<String>(settings.allNames.subList(groupSize, (groupSize*2))));
GroupNormalizer c = new GroupNormalizer(settings.allNames, new ArrayList<String>(settings.allNames.subList((groupSize * 2), (groupSize * 3))));
GroupNormalizer d = new GroupNormalizer(settings.allNames, new ArrayList<String>(settings.allNames.subList((groupSize * 3), (groupSize*4 + rest))));
a.start();
b.start();
c.start();
d.start();
编辑:所有4个线程在运行和监控(阻止)-status之间交替运行
答案 0 :(得分:3)
Executor Framework(线程池)来救援!
线程池管理工作线程池。线程池 包含一个工作队列,用于保存等待执行的任务。
答案 1 :(得分:2)
嗯,看起来这条线导致同步锁定:
if (proximity > Double.parseDouble(settings.properties.getProperty("distanceTreshold")) && proximity < 1.00)
尝试将Double.parseDouble拉出循环,因为那里的所有内容对我来说都是不变的。
似乎设置对象阻止了ob访问,这样会减慢你的速度。
在您的计算过程中看起来您正在访问数据库(捕获SQLEx),这会使您的速度降低很多。尝试将读取和写入与计算过程分开。
答案 2 :(得分:1)
试试ForkJoin。
答案 3 :(得分:0)
在多个线程中同时使用Java中的Double.parseDouble存在一个已知问题。它在内部用于解析的方法是同步的,因此如果你有很多线程同时调用它,那么线程最终会被阻塞。
这应该在Java 8中修复。
(参见Java错误报告JI-9004591 - “从多个线程调用Double.parseDouble时监视争用” - http://bugs.sun.com/view_bug.do?bug_id=7032154)
我怀疑这就是为什么在接受的答案(将Double.parseDouble移出)中所做的更改提高了性能。