我有一个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());
}
}
}
答案 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个主题,那么我建议
使用线程池 - 使用它们可以让事情变得更加容易
- 醇>
100个主题是很多线程,为什么选择这么多?这并不像拥有更多线程意味着更快地完成工作(并非总是至少)。 CPU必须做很多工作才能正确地使用它们,我不认为你在多核架构上使用这个应用程序。 (例如,&gt; 4)尝试扩展您的应用并运行一些测试,看看您是否从5-10线程到100获得任何改进。
编辑您没有一次运行所有100个线程,我仍然认为创建可能100个并发线程不是一个好选择。
不要扩展Thread,而是为Runnable创建一个实现
当然他们会混合结果,你一个接一个地启动Threads并不重要,它们运行的顺序总是不可预测的。
- 醇>
为了让它们正常工作你可以在SAME锁上同步它们,但是如果它们将一个接一个地执行,那么拥有100个线程的目的是什么?第二个线程将等待第一个,第三个将等待第二个等等......在这种情况下,你可以摆脱线程并只用一个。 或者您可以实现Callable而不是Runnable并将当前行号传递给每个Thread,当Thread完成时,它将返回带有它正在处理的行号的结果。将结果放入PriorityBlockingQueue并根据行号(使用比较器)对它们进行排序,然后只需获取它们并输出结果。
这里有人(我希望)会建议更多(我真的希望更好)解决方案;)
干杯,尤金。