我有这段代码:
public void GenerateWtW() {
ExecutorService exec = Executors.newFixedThreadPool(30);
ConcurrentHashMap<String, Double> tf_idfCache = new ConcurrentHashMap<String, Double>();
ArrayList<String> allwords = getAllWords();
int no_docs = getNumberOfDocs();
int cnt = 0;
for (int i = 0; i < allwords.size(); i++) {
String word1 = allwords.get(i);
if (i < allwords.size() - 1) {
for (int j = i + 1; j < allwords.size(); j++) {
String word2 = allwords.get(j);
cnt++;
if (word1.equals(word2)) {
continue;
}
//System.out.println("[" + cnt + "] WtW Started: " + word1 + "," + word2 + " No of Docs: " + no_docs + " Total No of words: " + allwords.size());
WTWThread t = new WTWThread(tf_idfCache, word1, word2, this, no_docs, db);
exec.execute(t);
}
}
}
exec.shutdown();
}
这是线程的代码:
private static class WTWThread implements Runnable {
private ConcurrentHashMap<String, Double> cacheRef;
private String word1, word2;
private WordRank workRankInstance;
private int no_docs;
private Database db;
public WTWThread(ConcurrentHashMap<String, Double> cacheRef, String word1, String word2, WordRank workRankInstance, int no_docs, Database db) {
this.cacheRef = cacheRef;
this.word1 = word1;
this.word2 = word2;
this.workRankInstance = workRankInstance;
this.no_docs = no_docs;
this.db = db;
}
@Override
public void run() {
double sum = 0;
for (int i = 1; i <= 10; i++) {
Double tf_idf1 = cacheRef.get(word1 + i);
if (tf_idf1 == null) {
tf_idf1 = workRankInstance.getTF_IDF(word1, i);
cacheRef.put(word1 + i, tf_idf1);
}
Double tf_idf2 = cacheRef.get(word2 + i);
if (tf_idf2 == null) {
tf_idf2 = workRankInstance.getTF_IDF(word2, i);
cacheRef.put(word2 + i, tf_idf2);
}
sum = sum + (tf_idf1 * tf_idf2);
}
double wtw = sum / no_docs;
String query = "INSERT INTO wtw(word1,word2,wtw) VALUES(?,?,?);";
try {
PreparedStatement ps = db.getConnection().prepareStatement(query);
ps.setString(1, word1);
ps.setString(2, word2);
ps.setDouble(3, wtw);
ps.executeUpdate();
ps.close();
} catch (SQLException ex) {
Logger.getLogger(WordRank.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
对我而言,一切看起来都不错,但这就是发生的事情,当我运行程序时,它处理前几百个然后突然停止!我检查了系统监视器,java进程开始增加内存使用量,它达到约1Gb,但没有任何反应。我想也许这种情况正在发生,因为我有太多的线程,我尝试了4个线程,但同样的事情发生了。然后我想也许我应该在创建线程之前使用sleep()并确实解决了问题,它就像魅力一样,但即使睡眠(1)也会让程序变得非常慢!我检查了一切我能想到的事情!这里有什么我想念的吗?
答案 0 :(得分:0)
听起来你要么有一个OutOfMemoryError,要么程序实际上没有停止,但由于内存使用的原因,磁盘交换已经接近停止。 1 GiB非常多。找出你是否有内存泄漏,可能是一个分析器。任何最近的JDK都捆绑了JVisualVM。
答案 1 :(得分:0)
你有多少个单词,你有多少内存以及这个程序在做什么?
你的tf_idfCache
将会变得非常大,至少会按字数增加,并且具有相当不变的因素(你要为每个单词缓存10个内容吗?),这可能会导致性能问题。
最后你确实遇到了并发问题,但我认为它不会导致锁定。在代码中
Double tf_idf1 = cacheRef.get(word1 + i);
if (tf_idf1 == null) {
tf_idf1 = workRankInstance.getTF_IDF(word1, i);
cacheRef.put(word1 + i, tf_idf1);
}
您无法保证不会两次计算等级。
我不认为线程数会导致任何问题,但是您可能会遇到导致锁定的其他并发问题(如果锁定,而不是内存开销根本就是问题)。