我在停止线程时遇到了一些麻烦。我有扫描文件夹中文件的方法。我想要一个停止扫描的按钮。点击此按钮后,线程将停止(扫描将停止)并且程序将重置。我尝试过命令 thread.stop();
有时它会起作用(它不再起作用)。因此,我在 stackoverflow 上阅读了一些主题,并尝试了 thread.interrupt();
我的代码如下所示:
public class myApp extends javax.swing.JFrame {
Thread thread;
int fileCount = 0;
String path = "C:\\Program Files";
public void scanningMethod() {
thread = new Thread(new Runnable() {
public void run() {
while(!thread.interrupted()){
//Recursion method that counting files
dirScan(path);
}
}
});
thread.start();
}
private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {
//generated button in netBeans
thread.interrupt();
thread.stop();
}
private void dirScan(String dirPath) {
File[] podSoubory = new File(dirPath).listFiles();
for (int i = 0; i < podSoubory.length; i++) {
if (podSoubory[i].isDirectory()) {
String tempPath = podSoubory[i].getAbsolutePath();
System.out.println(tempPath);
if (podSoubory[i].isFile()) {
fileCount++;
}
}
}
}
另一种停止方法仅包含thread.interrupt();
(ofc它有actionListener和其他东西)。
可能我做错了什么。您能帮我告诉我如何在单击按钮后停止这个正在运行的线程吗? (我知道如何创建可点击的按钮)。
最佳答案
至于你的主要问题,即为什么你的代码不起作用,我很抱歉,但我没有答案,因为不幸的是,我没有时间仔分割析和分析你的所有内容代码。我想说的是,你的代码是危险的代码(如你所知),不仅仅是因为你的调用 Thread#stop()
而且由于您的代码不遵守 Swing 线程规则,这些规则要求大多数 Swing 调用都在 Swing 事件线程上进行。您正在调用一些关键的 Swing 方法,包括 setText(...)
后台线程中的方法,这可能会导致间歇性非常难以调试的线程错误。
我建议:
- 出于多种原因,将 SwingWorkers 用于后台线程,但主要是为了您可以将后台线程中的数据安全地发布/处理到 GUI 中。
- 如果你想杀死你的 SwingWorker,请调用它的
cancel(true)
方法,传入true
参数允许此调用取消正在运行的代码。 - 在您的 SwingWorker 中,检查
isCancelled()
状态。 - 您想要后台线程的任何文本或数据都应传递到
publish(...)
在您的 SwingWorker 中调用doInBackground()
方法。 - SwingWorker 然后可以在其
process(...)
内处理这些数据。方法,保证在 Swing 事件线程上调用的方法。
例如:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
public class InterruptedGui {
private static final int GAP = 3;
private MyWorker myWorker;
private StartWorkerAction startWorkerAxn = new StartWorkerAction(this,
"Worker");
private StopAllAction stopAllAction = new StopAllAction(this, "Stop All");
private JLabel statusLabel = new JLabel("");
private JTextArea finalTextArea = new JTextArea(20, 40);
private JPanel mainPanel = new JPanel();
public InterruptedGui() {
finalTextArea.setFocusable(false);
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, 0));
buttonPanel.add(new JButton(startWorkerAxn));
buttonPanel.add(new JButton(stopAllAction));
JPanel statusPanel = new JPanel();
statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.LINE_AXIS));
statusPanel.add(new JLabel("Status: "));
statusPanel.add(statusLabel);
mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
mainPanel.setLayout(new BorderLayout());
mainPanel.add(buttonPanel, BorderLayout.PAGE_START);
mainPanel.add(new JScrollPane(finalTextArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
mainPanel.add(statusPanel, BorderLayout.PAGE_END);
}
public JComponent getMainPanel() {
return mainPanel;
}
public void setStatus(String text) {
statusLabel.setText(text);
}
public MyWorker getMyWorker() {
return myWorker;
}
public void setMyWorker(MyWorker myWorker) {
this.myWorker = myWorker;
}
public void finalTextAreaSetText(String text) {
finalTextArea.setText(text);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Interrupted Gui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new InterruptedGui().getMainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyWorker extends SwingWorker<String, String> {
private static final long SLEEP_TIME = 100;
private static final int MAX_COUNTER = 100;
private int counter = 0;
private InterruptedGui gui;
public MyWorker(InterruptedGui gui) {
this.gui = gui;
}
@Override
protected String doInBackground() throws Exception {
StringBuilder sb = new StringBuilder();
while (counter < MAX_COUNTER && !isCancelled()) {
counter++;
String statusText = "Counter is " + counter;
sb.append(statusText + "\n");
publish(statusText);
Thread.sleep(SLEEP_TIME);
}
return sb.toString();
}
@Override
protected void process(List<String> chunks) {
for (String statusText : chunks) {
gui.setStatus(statusText);
}
}
}
@SuppressWarnings("serial")
class StartWorkerAction extends AbstractAction {
private InterruptedGui gui;
public StartWorkerAction(InterruptedGui gui, String name) {
super(name);
this.gui = gui;
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
MyWorker myWorker = gui.getMyWorker();
if (myWorker != null && !myWorker.isDone()) {
return; // still running current worker
}
gui.finalTextAreaSetText("");
myWorker = new MyWorker(gui);
gui.setMyWorker(myWorker);
myWorker.addPropertyChangeListener(new WorkerPropertyListener(gui));
myWorker.execute();
}
}
class WorkerPropertyListener implements PropertyChangeListener {
private InterruptedGui gui;
public WorkerPropertyListener(InterruptedGui gui) {
this.gui = gui;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
MyWorker myWorker = gui.getMyWorker();
if (myWorker != null && !myWorker.isCancelled()) {
try {
String finalText = myWorker.get();
gui.finalTextAreaSetText(finalText);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
}
@SuppressWarnings("serial")
class StopAllAction extends AbstractAction {
private InterruptedGui gui;
public StopAllAction(InterruptedGui gui, String name) {
super(name);
this.gui = gui;
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
MyWorker myWorker = gui.getMyWorker();
if (myWorker == null) {
return;
}
myWorker.cancel(true);
}
}
关于java - 线程在中断或停止后不会停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31975337/