Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.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_Methods - Fatal编程技术网

在java中,使用按钮停止或退出方法有困难

在java中,使用按钮停止或退出方法有困难,java,methods,Java,Methods,我正在开发一个GUI程序来搜索重复的文件。我目前面临的问题是,当单击“搜索”按钮时,它会一直搜索,直到搜索完成。但是,我希望用户可以通过停止重复搜索方法来取消或停止搜索。我尝试在dupliate搜索方法中使用return语句,但它不起作用。这是我的密码: public void findDuplicateFiles(File[] files) throws IOException { Map<String, List<File>> filesByHash = n

我正在开发一个GUI程序来搜索重复的文件。我目前面临的问题是,当单击“搜索”按钮时,它会一直搜索,直到搜索完成。但是,我希望用户可以通过停止重复搜索方法来取消或停止搜索。我尝试在dupliate搜索方法中使用return语句,但它不起作用。这是我的密码:

public void findDuplicateFiles(File[] files) throws IOException  {
    Map<String, List<File>> filesByHash = new HashMap<>();
    if(stop.getText() == "stop")
        return;

    for (File file : files) {
        if (!file.isFile()) {
            findDuplicateFiles(file.listFiles());
            continue;  
        }
        String hash = MD5.asHex(MD5.getHash(file));

        List<File> filesForHash = filesByHash.get(hash);
        if (filesForHash == null) { 
            filesByHash.put(hash, filesForHash = new ArrayList<>());
        }
        filesForHash.add(file);
    }
    for (Map.Entry<String, List<File>> entry : filesByHash.entrySet()) {
        List<File> filesForHash = entry.getValue();
        if (filesForHash.size() > 1) {
            String hash = entry.getKey();
            System.out.printf("%,d files have hash %s:%n", filesForHash.size(), hash);
            int index = filesForHash.size() - 1;
            filesForHash.remove(index);
            final DefaultListModel model = (DefaultListModel) list.getModel();

            for (final File file : filesForHash) {
                EventQueue.invokeLater(new Runnable() {
                    public void run() {
                    pathf.setText("Searching Files...." + file.getPath());
                        try {
                            System.getProperty("com.twmacinta.util.MD5.NO_NATIVE_LIB.MD5.dll");
                            MD5.initNativeLibrary();
                            model.addElement(file.getCanonicalFile());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
                System.out.println("  " + file.getCanonicalPath());
            }
        }
    }
}
public void findDuplicateFiles(文件[]文件)引发IOException{
Map filesByHash=new HashMap();
if(stop.getText()=“stop”)
返回;
用于(文件:文件){
如果(!file.isFile()){
findDuplicateFiles(file.listFiles());
继续;
}
String hash=MD5.asHex(MD5.getHash(file));
List filesForHash=filesByHash.get(hash);
如果(filesForHash==null){
put(hash,filesForHash=newarraylist());
}
filesForHash.add(文件);
}
for(Map.Entry:filesByHash.entrySet()){
List filesForHash=entry.getValue();
if(filesForHash.size()>1){
String hash=entry.getKey();
System.out.printf(“%,d个文件具有哈希%s:%n”,filesForHash.size(),哈希);
int index=filesForHash.size()-1;
filesForHash.remove(索引);
最终的DefaultListModel=(DefaultListModel)list.getModel();
for(最终文件:filesForHash){
invokeLater(新的Runnable(){
公开募捐{
setText(“搜索文件…”+file.getPath());
试一试{
System.getProperty(“com.twmacinta.util.MD5.NO_NATIVE_LIB.MD5.dll”);
MD5.initNativeLibrary();
model.addElement(file.getCanonicalFile());
}捕获(IOE异常){
e、 printStackTrace();
}
}
});
System.out.println(“+file.getCanonicalPath());
}
}
}
}

感谢您的帮助。

我假设当stop.getText()为“stop”时,您希望结束该方法。 首先,“==”比较引用,而不是对象,因此它不起作用,您必须使用equals。以防万一,将其用作“stop.equalsIgnoreCase(stop.getText())。这种方式不区分大小写(可能getText返回“Stop”),并防止null(在getText返回null的情况下)

第二,在它所在的位置,如果它在检查文件夹的开始时“停止”,它将返回,但它将与它所在的文件夹的其余部分一起继续运行。 为了澄清,假设您有文件夹A、文件夹A/B和A下的许多文件。该方法刚刚输入了第一个for和stop。getText()更改为“stop”。
在这个示例中,您找到文件夹B并进行第二次调用,由于stop已激活,因此会立即返回,但第一次调用将继续处理文件夹a中的其余文件。实际上,您通过使用
EventQueue.invokeLater
向调用队列添加一个新线程来“计划”所有文件的处理。在编写代码时,您不会对创建的Runnable保留任何引用,而且,即使可能,保留所有Runnable并取消它们也不是一个好主意,因为您无法真正预测它们的状态和全部

然后,由于它们都是计划好的,它们运行时没有办法阻止它们,因为您的主线程不再直接引用它们

解决问题的最佳方法可能看起来有点复杂,但也应该帮助您更好地理解多线程:创建一个新类,该类实现Runnable,但还提供一个“stop”方法(随意命名)。这个新类将包含类似于您发布的代码的内容,但不会使用invokeLater或类似的东西,它将直接执行整个过程,并以尽可能最好的粒度添加检查

下面是它的外观:

public class DuplicateDetector implements Runnable{

private boolean canContinue = true;

public void run(){
    // prepare the file list and do the stuff you do not want to
    // run on the main thread
    this.startDetection();
}

private void startDetection(){
    for(File f : this.allYourFiles){

      // HERE IS THE KEY TO STOP YOU THREAD
      // Of course, this will only be checked once per file so
      // it will wait until the current file is finished before stopping
      // the execution
      if(this.canContinue){
         ...
      else{
        break;
      }
    }
    // detection finished, you can know if it ended naturally or because
    // of the cancel button with the value of this.canContinue
    // and provide the feedback you want
}

public synchronized void stop(){
  this.canContinue = false;
}

// Other possible functions to prepare the file list and stuff
}
在管理UI的同一线程中,您将在
Runnable
类上保留一个引用,这样您就可以在按钮的click事件处理程序的某个地方使用它的stop函数

我正在考虑类似的事情(您也可以使用EventQueue.invokeLater):

在按钮的单击处理程序中,您可以使用

dupDet.stop()
安全,因为它是同步的。然后,复制检测器将在下次检查
canContinue
的值时正常停止

也有一些阴暗的方法可以杀死线程,但它们几乎都一个接一个地被弃用<代码>中断是正确的方法,但它不允许您的线程在取消后提供反馈,如处理了多少文件、找到了重复项等

IMO的一个好方法是在执行过程中提供反馈,这对用户总是有好处的。它可以像从主线程定期访问的replicationdetector中的
getProgression
public方法一样简单,让您的想象力尽情发挥


我希望这有帮助

您必须在新线程上保留一个引用,并在单击按钮时将其终止,或者以线程经常循环的方式设计线程(例如,每个文件一次),并检查外部范围中的变量是否允许它进一步运行。第一种方法更安全,但如果做得不好,可能会导致不干净的停机。@Johnride请你举个例子,我不太明白你的意思。我们需要更多的细节才能提供帮助。首先,你说“它不起作用”。你的确切意思是什么?它从不停止,停止得不够快,或者抛出异常?其次-调用
stop.getText()
-我们看不到stop变量是什么。这是JButton吗?当你点击时,文本真的在变化吗
dupDet.stop()