阻止运行SAX Parser的线程

时间:2017-01-18 21:07:22

标签: java multithreading xml-parsing

我在使用多线程来阻止我的应用程序运行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()

  • 使用替代锁定系统,但它似乎没有阻止我的sax解析器....

1 个答案:

答案 0 :(得分:1)

SAXParser是一个基于事件的解析器 - 最古老,最不方便的XML解析器类型。您经历过的问题是它完全控制了解析,您只能做出反应;你不能再采取行动了。

您有两种选择:

  1. 创建一个可停止的InputStream,以便您可以通过停止其输入来停止解析器。它可能仍然有一些数据被缓冲,但它会很快停止。

  2. 使用流式传输或拉式解析器解析器(请参阅example)。它不控制解析。相反,您驱动解析并请求下一个XML元素。当你处于控制之中时,停下它是一件容易的事。

  3. 选项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。