Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中停止线程后,如何重新启动它?_Java_Multithreading_Restart - Fatal编程技术网

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

在Java中停止线程后,如何重新启动它?,java,multithreading,restart,Java,Multithreading,Restart,在我用java编写的项目中手动停止线程后,我试图重新启动线程。当我尝试重新启动它时,出现了一个非法ThreadStateException错误 我将代码简化为以下示例代码。我的问题是: 如何重新启动logtest线程,是否必须启动新线程而不是重新启动它 从下面的代码中可以看到,在LogThread类的run方法中,我使用Thread.Sleep(3)逐行输出这些数字。如果我删除这一行,线程要么在中间死亡,要么同时输出所有这10000行。我是否必须强制线程停止3毫秒以牺牲其性能?有没有更好的办法解

在我用java编写的项目中手动停止线程后,我试图重新启动线程。当我尝试重新启动它时,出现了一个非法ThreadStateException错误

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

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

  • 从下面的代码中可以看到,在LogThread类的run方法中,我使用Thread.Sleep(3)逐行输出这些数字。如果我删除这一行,线程要么在中间死亡,要么同时输出所有这10000行。我是否必须强制线程停止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;    
      }
    }
    
    导入java.awt.BorderLayout;
    导入java.awt.Container;
    导入java.awt.event.ActionEvent;
    导入java.awt.event.ActionListener;
    导入javax.swing.JButton;
    导入javax.swing.JFrame;
    导入javax.swing.JScrollPane;
    导入javax.swing.JTextPane;
    导入javax.swing.text.StyledDocument;
    公共类日志测试{
    私有日志线程日志测试;
    公共日志测试(){
    JFrame=新JFrame(“LogTest”);
    容器con=frame.getContentPane();
    最终JTextPane=新的JTextPane();
    最终JScrollPane scollPane=新的JScrollPane(窗格);
    JButton按钮=新JButton(“启动测试日志”);
    JButton button1=新JButton(“停止测试日志”);
    logtest=新的LogThread(窗格);
    con.add(scollPane);
    con.add(按钮,BorderLayout.NORTH);
    con.添加(按钮1,边界布局。南部);
    addActionListener(新建ActionListener()){
    已执行的公共无效操作(操作事件e){
    logtest.start();
    }
    });
    button1.addActionListener(新ActionListener(){
    已执行的公共无效操作(操作事件e){
    logtest.stop();
    }
    });
    框架设置尺寸(600500);
    frame.setVisible(true);
    }
    公共静态void main(字符串[]args){
    新LogTest();
    }
    }
    类LogThread实现Runnable{
    私有最终线程t;
    私有字符串换行符;
    私有易失性布尔值shouldStop=false;
    私人文件;
    私人JTextPane;
    专用静态整数计数器=0;
    公共日志线程(JTextPane窗格){
    this.doc=pane.getStyledDocument();
    this.pane=窗格;
    t=新线程(此为“日志线程”);
    newline=System.getProperty(“line.separator”);
    }
    公开作废开始(){
    t、 start();
    }
    公开募捐{
    试一试{
    如果(doc.getLength()>0){
    doc.remove(0,doc.getLength());
    }
    }捕获(例外e){
    e、 printStackTrace();
    }
    如果(shouldStop)shouldStop=false;
    
    对于(inti=counter;i基本上,从

    启动一个线程超过一次是不合法的 线程一旦完成执行,就不能重新启动

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

    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
    并从
    过程
    方法中更新UI


    查看更多详细信息

    您不能。
    线程
    是不可重入的,这意味着您不能对其多次调用
    开始
    。您需要创建一个新的
    线程
    并向其传递一个对
    可运行
    实例的引用,然后启动该
    线程