Java多线程将文本混合在不工作的输出文件锁中

时间:2012-02-09 10:00:49

标签: java multithreading

我有一个Java应用程序,我在其中启动了100个线程。线程在解析xml文件并从中提取一些文本后,打开一个文件来编写提取的文本。但是,它们似乎混合了结果(输出文件不是按照假定的顺序)。 我使用Lock但它没有解决问题。有人可以帮忙吗?

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());
     }
}




}

3 个答案:

答案 0 :(得分:3)

该行:

Lock l=new ReentrantLock();
SimpleThread.run()中的

将为SimpleThread的每个实例创建一个新锁,这是无意义的,并且所有线程之间的唯一同步将是FileWrite()方法。如果您想要SimpleThread的所有实例共享锁,请添加static Lock成员变量:

static Lock l = new ReentrantLock();

然而,这样做意味着线程将按顺序执行,这使得线程完全毫无意义。

替代方法是SimpleThread解析其XML文件(不需要锁定)并将结果缓存到内存中(在ArrayList<String>()中存储要写入文件的行)。 main()线程将等待所有SimpleThread个实例完成,然后将每个实例的结果写入文件。这将允许解析XML并发并确保有序的输出文件。

答案 1 :(得分:0)

您可以尝试“同步”,这至少可以确保您的一个线程正在运行。

答案 2 :(得分:0)

如果您使用的是100个主题,那么我建议

  
      
  1. 使用线程池 - 使用它们可以让事情变得更加容易

  2.   
  3. 100个主题是很多线程,为什么选择这么多?这并不像拥有更多线程意味着更快地完成工作(并非总是至少)。 CPU必须做很多工作才能正确地使用它们,我不认为你在多核架构上使用这个应用程序。 (例如,&gt; 4)尝试扩展您的应用并运行一些测试,看看您是否从5-10线程到100获得任何改进。

  4.   

编辑您没有一次运行所有100个线程,我仍然认为创建可能100个并发线程不是一个好选择。

  
      
  1. 不要扩展Thread,而是为Runnable创建一个实现

  2.   
  3. 当然他们会混合结果,你一个接一个地启动Threads并不重要,它们运行的​​顺序总是不可预测的。

  4.   
  5. 为了让它们正常工作你可以在SAME锁上同步它们,但是如果它们将一个接一个地执行,那么拥有100个线程的目的是什么?第二个线程将等待第一个,第三个将等待第二个等等......在这种情况下,你可以摆脱线程并只用一个。   或者您可以实现Callable而不是Runnable并将当前行号传递给每个Thread,当Thread完成时,它将返回带有它正在处理的行号的结果。将结果放入PriorityBlockingQueue并根据行号(使用比较器)对它们进行排序,然后只需获取它们并输出结果。

  6.   

这里有人(我希望)会建议更多(我真的希望更好)解决方案;)

干杯,尤金。