在Java中停止线程后,如何重新启动它?
在我用java编写的项目中手动停止线程后,我试图重新启动线程。当我尝试重新启动它时,出现了一个非法ThreadStateException错误 我将代码简化为以下示例代码。我的问题是:在Java中停止线程后,如何重新启动它?,java,multithreading,restart,Java,Multithreading,Restart,在我用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
查看更多详细信息您不能。线程
是不可重入的,这意味着您不能对其多次调用开始
。您需要创建一个新的线程
并向其传递一个对可运行
实例的引用,然后启动该线程