我在使用多线程来阻止我的应用程序运行SAX解析器时遇到问题。
我有一个读取XML文件的类,逐行,我希望能够在按下按钮时停止它:
private String filename;
private boolean paused = false;
public xmlReader(String filename) {
this.filename = filename;
}
public void run() {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
// when an open row is encountered in the posts.xml file
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (!paused) {
System.out.println("Start Element :"
+ attributes.getValue("name"));
}
}
}
saxParser.parse (filename, handler);
这是读取xml文件的代码,但是因为我希望能够暂停和恢复run方法,所以我从一个线程调用它:
public class myThread implements Runnable {
private String file;
private TextArea Suggestions;
private volatile boolean running = true;
private volatile boolean paused = false;
databaseReader db = new databaseReader(this.file);
public void setSuggestions(TextArea Suggestions) {
this.Suggestions = Suggestions;
}
public void setFile(String dbFile) {
this.file = dbFile;
}
public void stop() {
running = false;
// you might also want to do this:
}
public void pause() {
// you may want to throw an IllegalStateException if !running
paused = true;
}
public void resume() {
synchronized (db) {
paused = false;
db.notifyAll(); // Unblocks thread
}
}
@Override
public void run() {
while (running) {
synchronized (db) {
db.run();
if (!running) {
break;
}
if (paused) {
try {
System.out.println("paused");
db.wait();
} catch (InterruptedException ex) {
break;
}
if (!running) {
break;
}
}
}
}
throw new UnsupportedOperationException("Not supported yet.");
//To change body of generated methods, choose Tools | Templates.
}
同样,我有一个按钮可以在按下时更改线程上isRunning的值:
if (!isRunning) {
myThread search = new myThread();
search.start();
}
然而,这似乎都没有阻止线程,所以即使在关闭应用程序之后线程仍继续运行。
我尝试过的其他事情 - 交换实现Runnable而不是扩展线程类并调用interrupt,wait()
答案 0 :(得分:1)
SAXParser
是一个基于事件的解析器 - 最古老,最不方便的XML解析器类型。您经历过的问题是它完全控制了解析,您只能做出反应;你不能再采取行动了。
您有两种选择:
创建一个可停止的InputStream
,以便您可以通过停止其输入来停止解析器。它可能仍然有一些数据被缓冲,但它会很快停止。
使用流式传输或拉式解析器解析器(请参阅example)。它不控制解析。相反,您驱动解析并请求下一个XML元素。当你处于控制之中时,停下它是一件容易的事。
选项1或多或少的工作原理如下:
public class StoppedException extends RuntimeException {
}
public class StoppableInputStream extends InputStream {
private boolean stopped;
private InputStream wrappedStream;
public StoppableInputStream(InputStream wrapped) {
wrappedStream = wrapped;
}
public boolean isStopped() {
return stopped;
}
public void setStopped(boolean stopped) {
return this.stopped = stopped;
}
public int read() {
if (stopped)
throw new StoppedException();
return wrappedStream.read();
}
public int read(byte[] b) {
if (stopped)
throw new StoppedException();
return wrappedStream.read(b);
}
public int read(byte[] b, int off, int len) {
if (stopped)
throw new StoppedException();
return wrappedStream.read(b, off, len);
}
// do the same for all other methods of InputStream
}
然后像这样初始化解析器:
FileInputStream fis = new FileInputStream("yourfilename.xml");
StoppableInputStream sis = new StoppableInputStream(fis);
saxParser.parse (filename, handler);
最后,你停止解析器:
sis.setStopped(true);
我没有测试过代码。它甚至可能无法编译。
我建议你选择2。