2012-02-09 4 views
2

私は100スレッドを開始するJavaアプリケーションを持っています。スレッドは、xmlファイルを解析し、そこから何らかのテキストを抽出した後、抽出したテキストを書き込むためにファイルを開きます。しかし、結果が混ざっているように見えます(出力ファイルは想定された順序ではありません)。 私はLockを使用しましたが、問題は解決しませんでした。誰も助けることができますか?Javaマルチスレッドがテキストを混在させて出力ファイルをロックしない

Main.java 


public class Main { 




    public static void main(String[] args) throws FileNotFoundException, IOException, InterruptedException { 



    FileInputStream fstream = new FileInputStream("C:\\Users\\Michael\\outfilenames0.txt"); 

    BufferedReader br = new BufferedReader(new InputStreamReader(fstream)); 

    String strLine; 


    int j=0; 

    while (((strLine = br.readLine()) != null) && (j<100)) 

    { 
     int activethreads=Thread.activeCount(); 


     SimpleThread t=new SimpleThread(strLine); 
     t.start(); 

     if (activethreads>100) 
      SimpleThread.sleep(250); 
     if (j==99) 
     {j=-1;} 

     //System.out.println(t.getName()); 
     j++; 


    } 

    } 

} 




class SimpleThread extends Thread { 


    private String str; 


    public SimpleThread(String str) { 
     this.str=str; 

    } 
    @Override 
    public void run() { 


     try { 
      Lock l=new ReentrantLock(); 
      if (l.tryLock()){ 
       try { 
       SAXParserFactory factory = SAXParserFactory.newInstance(); 

      // create SAX-parser... 
       SAXParser parser=factory.newSAXParser(); 

      SaxHandler handler = new SaxHandler(); 
      parser.parse(str, handler); 
       } catch (ParserConfigurationException ex) { 
        Logger.getLogger(SimpleThread.class.getName()).log(Level.SEVERE, null, ex); 
       }finally {l.unlock();} 

      } else Thread.currentThread().sleep(10); 


     } catch (InterruptedException ex) { 

      Logger.getLogger(SimpleThread.class.getName()).log(Level.SEVERE, null, ex); 

     } catch (SAXException ex) { 

      Logger.getLogger(SimpleThread.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (IOException ex) { 

      Logger.getLogger(SimpleThread.class.getName()).log(Level.SEVERE, null, ex); 
     } 

    } 

} 






    class SaxHandler extends DefaultHandler { 

     private boolean invention_title = false; 
     private boolean invention_title_lang = false; 

     private boolean abstr = false; 
     private boolean abstr_lang = false; 

     private boolean descr = false; 
     private boolean description_lang = false; 

     private String doc=""; 
     private String ucid; 

     @Override 
     public void startElement(String uri, String localName, 
       String qName, Attributes attrs) throws SAXException { 

      if (qName.equals("patent-document")) { 

       ucid = attrs.getValue("ucid"); 
       doc= ("<DOC>\n<DOCNO> " + ucid +"</DOCNO> \n<TEXT>"); 
          } 

      if (qName.equalsIgnoreCase("invention-title")) { 
         invention_title = true; 
         String title_language = attrs.getValue("lang"); 
         if (title_language.equals("EN")) 
         { 
          invention_title_lang = true; 
          doc=doc+"<TITLE>"+"\n"; 
              } 
            } 

      if (qName.equalsIgnoreCase("abstract")) { 
         abstr = true; 
         String abst_language = attrs.getValue("lang"); 
         if (abst_language.equals("EN")) {abstr_lang = true; 
         doc=doc+"<ABSTRACT>"+"\n" ; 
             } 
         } 


      if (qName.equalsIgnoreCase("description")) { 
         descr = true; 
         String des_language = attrs.getValue("lang"); 
         if (des_language.equals("EN")) {description_lang = true; 
         doc=doc+"<DESCRIPTION>"+"\n"; 
             } 
           }} 


@Override 


public void endElement (String uri, String localName, String qName) 
throws SAXException 
{ 
    if((qName.equals("abstract"))&& (abstr_lang)){ 
     abstr_lang = false; 
     doc=doc+"</ABSTRACT>"+"\n"; 
     } 

    if((qName.equals("invention-title"))&&(invention_title_lang)){ 
     invention_title_lang = false; 
     doc=doc+"</TITLE>"+"\n"; 
     } 

    if((qName.equals("description"))&&(description_lang)){ 
     description_lang = false; 
     doc=doc+"</DESCRIPTION>"+"\n"; 
     } 

     if(qName.equals("patent-document")){ 
     doc=doc+"</TEXT>"+"\n"+"</DOC>"+"\n"; 
     //System.out.println("</DOC>"); 
      //Lock l=new ReentrantLock(); 

     // if (l.tryLock()) 
      //try { 


       FileWrite fileWrite = new FileWrite(); 
       try { 
        fileWrite.FileWrite(ucid, doc); 
       } catch (IOException ex) { 
        Logger.getLogger(SaxHandler.class.getName()).log(Level.SEVERE, null, ex); 
       } 
      // }finally {l.unlock();} 
       // catch (IOException ex) { 
       //Logger.getLogger(SaxHandler.class.getName()).log(Level.SEVERE, null, ex); 
      // } 

    } 

    } 

     @Override 
     public void characters(char ch[], int start, int length) 
throws SAXException { 


       if (invention_title_lang) { 
         doc=doc+ (new String(ch, start, length))+"\n";     
       } 

       if (abstr_lang) { 
        doc=doc+ (new String(ch, start, length)); 

       } 

       if (description_lang) { 
        doc=doc+ (new String(ch, start, length)); 
         } 
      } 
} 




class FileWrite 
{ 

public synchronized void FileWrite(String ucid, String doc) throws IOException 

{ 
    Thread t=Thread.currentThread(); 
try{ 



    FileWriter fstreamout = new FileWriter("EP-022",true); 
    BufferedWriter out = new BufferedWriter(fstreamout); 
    out.write(doc); 
    out.close(); 

    if (t.isAlive()) 
    { 
    t.stop();} 
    } 
catch (Exception e) 
{ 
System.err.println("Error"+e.getMessage()); 
    } 
} 




} 
+0

どのようなご注文を予定していますか? – pingw33n

答えて

3

ライン:SimpleThread.run()

Lock l=new ReentrantLock(); 

は無意味であり、すべてのスレッド間でのみ同期がFileWrite()方法なりSimpleThreadのインスタンスごとに新しいロックを作成します。あなたがSimpleThreadのすべてのインスタンスで共有ロックを持つようにしたい場合は、static Lockメンバ変数を追加:

static Lock l = new ReentrantLock(); 

をしかし、そうすることは、すべてのスレッドを持つ、それはかなり無意味になりれ、スレッドが順次実行することを意味します。

SimpleThreadはXMLファイル(ロックの必要なし)を解析し、メモリに結果をキャッシュすることができます(ファイルに書き込まれる行を格納するArrayList<String>())。 main()スレッドは、すべてのSimpleThreadインスタンスが完了するまで待機し、各インスタンスの結果をファイルに書き込みます。これにより、XMLの構文解析が並行して行われ、順序付けされた出力ファイルが確保されます。

+0

+1。仰るとおりです。また、FileWriteクラスの同期コンストラクタのパラメータである "ucid"という文字列は使用されず、推奨されないstop()Threadメソッドの使用は推奨されません。なぜなら、t.interrupt()を呼び出すほうが良いからです。 –

0

「同期」を試してみてください。少なくとも、スレッドの1つが実行中であることを確認してください。

0

あなたは100個のスレッドを使用している場合は、私はスレッドプールを使用し

  1. を示唆している - 物事は彼らと

  2. 100スレッドをそんなに簡単に得ることができることは、スレッドのLOTですなぜあなたはそんなに多くを選んだのですか?それ以上のスレッドを持つようなものではありません。 CPUはそれらを正しく再生するために多くの作業を行う必要があり、私はあなたがマルチコアアーキテクチャでこのアプリケーションを使用しているとは思わない。 (> 4例)すべての100個のスレッドを実行していないあなたは100

EDITに5-10スレッドから任意の改善を得るかどうかを確認するためにあなたのアプリケーションを拡張し、いくつかのテストを実行してみます一度に、潜在的に100の同時スレッドを作成するのは良い選択ではないと私はまだ考えています。

  1. 彼らは結果を混合するスレッドを拡張し、もちろんRunnableを

  2. の実装を作成しないでください、あなたが他の後に1つに彼らの順序スレッドは起動していることは重要ではありません。実行は常に予測不可能です。

  3. 正常に動作させるには、SAMEロックで同期させることができますが、次々に実行するスレッドが100個あるという目的は何ですか?2番目のスレッドは最初に待っています.3番目のスレッドは2番目のスレッドを待つことになります。この場合、スレッドを取り除いて1つだけ実行できます。 または、Runnableの代わりにCallableを実装して、各スレッドにcurrect行番号を渡すことができます。スレッドが終了すると、処理していた行番号の結果が返されます。その結果をPriorityBlockingQueueに入れ、(Comparatorを使用して)行番号に従ってソートしてから、結果を出力してください。

(私は願っています)おそらくよりを示唆して(と私は本当に良く願っています)しますここの人々のソリューションもあります。)

乾杯、ユージン。

関連する問題