在Java中停止后,如何重新启动线程?

时间:2014-07-08 01:28:29

标签: java multithreading restart

在我用java编写的Project中手动停止后,我试图重新启动一个线程。当我尝试重新启动它时,我发出了IllegalThreadStateException错误。

我将我的代码简化为以下示例代码。我的问题是:

  1. 如何重新启动logtest线程,是否必须启动新线程而不是重新启动它?

  2. 从下面的代码可以看出,在LogThread类的run方法中,我使用 Thread.Sleep(3)逐行输出这些数字。如果我删除这一行,线程将在中间死亡或一次输出所有这10000行。我是否必须强制线程停止3毫秒才能牺牲其性能?有没有更好的方法来解决这个问题?

  3. 守则:

    import java.awt.BorderLayout;
    import java.awt.Container;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextPane;
    import javax.swing.text.StyledDocument;
    
    public class LogTest {
      private LogThread logtest;
      public LogTest() {
        JFrame frame = new JFrame("LogTest");
        Container con = frame.getContentPane();
        final JTextPane pane = new JTextPane();
        final JScrollPane scollPane = new JScrollPane(pane);
        JButton button = new JButton("Start Test Log");
        JButton button1 = new JButton("Stop Test Log");
        logtest = new LogThread(pane);
        con.add(scollPane);
        con.add(button, BorderLayout.NORTH);
        con.add(button1, BorderLayout.SOUTH);
        button.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            logtest.start();
          }
        });
        button1.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            logtest.stop();
          }
    
        });
        frame.setSize(600, 500);
        frame.setVisible(true);
      }
    
      public static void main(String[] args) {
        new LogTest();
      }
    
    }
    
    class LogThread implements Runnable {
      private final Thread t;
      private String newline;
      private volatile boolean shouldStop = false;
      private StyledDocument doc;
      private JTextPane pane;
      private static int counter = 0;
    
      public LogThread(JTextPane pane) {
        this.doc = pane.getStyledDocument();
        this.pane = pane;
        t = new Thread(this, "Log Thread");
        newline = System.getProperty("line.separator");
      }
    
      public void start() {
        t.start();
      }
    
      public void run() {
        try {
          if (doc.getLength() > 0) {
            doc.remove(0, doc.getLength());
          }
        } catch (Exception e) {
          e.printStackTrace();
        }
        if(shouldStop) shouldStop=false;
        for (int i = counter; i <= 1000 && !shouldStop; i++) {
          try {
            doc.insertString(doc.getLength(),
                i + "-------------------------------------------------------------"+ newline,
                null);
            pane.setCaretPosition(doc.getLength());
            Thread.sleep(3);
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    
      public void stop() {
        shouldStop = true;    
      }
    }
    

1 个答案:

答案 0 :(得分:3)

基本上,您不能来自JavaDocs ...

  

不止一次启动线程永远不合法。特别是,a   一旦完成执行,线程可能无法重新启动。

您需要做的是,在调用start时,创建一个新的Thread,将this传递给它并启动该线程。您需要确定Thread是否已在运行并采取措施首先终止它

class LogThread implements Runnable {
  private final Thread t;
  //....

  public LogThread(JTextPane pane) {
      //...
      //t = new Thread(this, "Log Thread");
      //...
  }

  public void start() throws InterruptedException {
    if (t != null && t.isAlive()) {
        shouldStop = true;
        t.join();
    }
    shouldStop = false;
    t = new Thread(this, "Log Thread");
    t.start();
  }

  //...

  public void stop() throws InterruptedException {
    shouldStop = true;    
    t.join();
    t = null;
  }
} 

您还通过在事件调度线程的上下文之外修改UI的状态来违反Swing的单线程规则...

特别是......

pane.setCaretPosition(doc.getLength());

更安全的解决方案是使用SwingWorker并从process方法中更新用户界面。

请查看How to use SwingWorker了解详情