多线程导致程序停止?

时间:2011-10-19 17:04:57

标签: java

我有这段代码:

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)也会让程序变得非常慢!我检查了一切我能想到的事情!这里有什么我想念的吗?

2 个答案:

答案 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);
}

您无法保证不会两次计算等级。

我不认为线程数会导致任何问题,但是您可能会遇到导致锁定的其他并发问题(如果锁定,而不是内存开销根本就是问题)。