在我用java编写的Project中手动停止后,我试图重新启动一个线程。当我尝试重新启动它时,我发出了IllegalThreadStateException错误。
我将我的代码简化为以下示例代码。我的问题是:
如何重新启动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;
}
}
答案 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了解详情