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

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




}

最佳答案

行:

Lock l=new ReentrantLock();

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

static Lock l = new ReentrantLock();

但是,这样做意味着线程将按顺序执行,这使得拥有线程毫无意义。

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

关于Java多线程在不工作的输出文件锁定中混合文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9208726/

相关文章:

java - 线程中断不起作用

java - 计算字符串的字母(大写和小写)

java - Set<Tuple> 未正确添加值

java - 与 Java 中的多处理相比,多线程性能较差

python - 如何在异步函数中使用 threading.Lock 而可以从多个线程访问对象

java - 确认同步概念

java - 在运行时加载 Java 字节代码

java - 无法在包中找到类

java - MySQL 数据库存储未知数量的值

java - JVM 在创建线程并在其中执行网络操作时突然关闭