2011-10-19 6 views
0

私はこのコードを持っている:マルチスレッドはプログラムを停止させますか?

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()を使用して問題を解決したはずですが、それは魅力的に機能しましたが、sleep(1)でもプログラムが非常に遅くなりました。私は考えることができるすべての可能性をチェックしました!私はここに欠けているものはありますか?

答えて

0

あなたは何語持っていますか?どのくらいのRAMがありますか?このプログラムは何をしていますか?

あなたの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); 
} 

ランクを2度計算しないという保証はありません。

スレッド数が問題を引き起こしているとは思えませんが、ロックを引き起こしている他の並行性の問題があるかもしれません(ロックされていて、メモリオーバーヘッドに問題はありません)。

+0

ヒープスペースの問題ではなく、ヒープに2GBを割り当てました。問題は、スレッドが非常に速く成長していることと、私はjvmがそれを処理できないと考えていることです。私が言ったように、私はそれの前に遅れを入れ、すべてがうまくいく!メモリリークはなく、ロック状態もありません。私はスレッドプールについて何かする必要があると思う。 – Tohid

+0

あなたはスレッドを作っておらず、固定数のスレッド(あなたの例では30)に分散されるべきRunnableオブジェクトを作っている。彼らはおそらく彼らが仕事を終えた直後にゴミ収集されます。 – Slartibartfast

0

あなたはOutOfMemoryErrorを持っているか、プログラムが実際に停止しなかったのと同じように聞こえていますが、メモリ使用量のためにディスクスワッピングによってほぼ停止してしまいます。 1 GiBはかなりです。おそらくプロファイラでメモリリークがあるかどうか調べてください。最近のJDKにはJVisualVMがバンドルされています。

+0

私はsleep()をスレッドコールの前に置くとうまくいきました。パフォーマンスに関する問題があるかもしれませんが、リークの問題はないと思います。 – Tohid

関連する問題