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_Swing_Sftp_Jprogressbar - Fatal编程技术网

Java 在线程完成后调用函数

Java 在线程完成后调用函数,java,multithreading,swing,sftp,jprogressbar,Java,Multithreading,Swing,Sftp,Jprogressbar,我正在使用Jsch编写一个Sftp客户端程序。我使用JProgressBars来显示上传和下载的进度。我的GUI包含与我的工作目录中的文件相对应的按钮。删除文件时,我更新了gui以向用户提供反馈: void update() { panel.removeAll(); addToPanel(ls(channelsftp, sftpWorkingDir)); validate(); } 这是使用my ls函数返回当前workingDir中的所有文件。addToPanel将处

我正在使用Jsch编写一个Sftp客户端程序。我使用JProgressBars来显示上传和下载的进度。我的GUI包含与我的工作目录中的文件相对应的按钮。删除文件时,我更新了gui以向用户提供反馈:

void update() {
    panel.removeAll();
    addToPanel(ls(channelsftp, sftpWorkingDir));
    validate();
}
这是使用my ls函数返回当前workingDir中的所有文件。addToPanel将处理面板上的“输入到输出”按钮。这对于删除文件非常有效。但是,我希望在上传完成后调用相同的更新函数。由于upload以JProgressBar的形式向我提供图形反馈,其功能已转移到线程:

final JFileChooser uploadChooser = new JFileChooser();
    ulo.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            int returnVal = uploadChooser.showOpenDialog(Navigator.this);
            if(returnVal == JFileChooser.APPROVE_OPTION) {
                String pathToUpload = uploadChooser.getSelectedFile().getAbsolutePath();
                Runnable uploadIt = new UploadUtil(pathToUpload, chacha);
                new Thread(uploadIt).start();
            }   
        }
    });
因此,当用户在这个JFileChooser中单击OK之后,上传就开始了。以下是UploadUtil:

public class UploadUtil implements Runnable{

    String paTU;
    ChannelSftp csftp;

    public UploadUtil(String pathToUl, ChannelSftp chaSftp) {
        paTU = pathToUl;
        csftp = chaSftp;
    }

    @Override
    public void run() {
        try {
            csftp.put(paTU, LoginAndFunctions.sftpWorkingDir, new SystemOutProgressMonitor());
        } catch (SftpException e) {
            Error errorUploading = new Error(e.toString()+"\nUploadpipe closed unexpectedly");
            errorUploading.setVisible(true);
        }
    }
}
SystemOutpressMonitor是一个在Jsch中处理数据传输的类。
我尝试使用Thread.join()和CountDownLatch。两者都阻止了我的JProgressBar更新。有不同的解决方案吗?

解决方案是使用回调方法或机制。因为这是一个Swing问题,所以在一个线程中使用SwingWorker,而不是Runnable,它提供了两种潜在的方法

  • 当Swing事件线程的worker中的
    done()
  • 或者将PropertyChangeListener添加到SwingWorker,侦听“state”属性,并在新值为
    SwingWorker.StateValue.DONE
    时做出反应
请注意,还可以将PropertyChangeListener添加到工作线程并侦听其progress属性。在worker内更新数据时,使用0到100之间的值调用
setProgress(int-value)
来更新此属性。然后在侦听器中,使用此值更新JProgressBar

例如(请注意,代码尚未测试,如果出现错误,请道歉):

然后使用它:

public void actionPerformed(ActionEvent arg0) {
    int returnVal = uploadChooser.showOpenDialog(Navigator.this);
    if(returnVal == JFileChooser.APPROVE_OPTION) {
        String pathToUpload = uploadChooser.getSelectedFile().getAbsolutePath();
        UploadUtil uploadIt = new UploadUtil(pathToUpload, chacha);
        uploadIt.addPropertyChangeListener(new UploadUtilListener());
        uploadIt.execute();
    }   
}

这对我没用。实际上SystemOutpressMonitor已经有一个end()函数,该函数在进程完成后调用。我可以在那里调用update,但是更新需要是静态的。它不可能是静态的,因为我在那里打电话。将对扩展JFrame的Navigator类调用validate()。我遗漏了什么吗?@RonnyBrandt:那么你的问题并不像你在问题中完全描述的那样,因为这确实显示了一个有效的解决方案,当后台线程完成时,如何在Swing事件线程上调用Swing代码。如果这不起作用,那么你需要更新你的问题,主要是通过创建和发布一个有效的。对于您的MCVE,请使用
Thread.sleep
模拟长期运行的后台进程,因为这将允许我们运行您的代码,而不需要我们没有的文件和依赖项。是的,它现在正在工作。我的解决方案是使用Navigator调用UploadUtil。这可以解决静态/非静态问题。。。谢谢你的帮助;)@罗尼布兰特:我很高兴你把事情解决了。我必须指出,不应该存在静态/非静态问题。除了主方法之外的所有方法,也许还有一些单例,都应该在实例(非静态)世界中运行。如果您对此有疑问,它建议您的代码可以从重新设计中受益。祝你好运一切都在“实例”世界中运行。我的main方法只创建另一个类的一个对象,它只有两行代码。但是我创建了一个UploadUtil对象。UploadUtil无法在导航器上调用validate()。但是当我实例化UploadUtil时,我可以传递我的Navigator对象。我应该重新设计这个吗?
class UploadUtilListener implements PropertyChangeListener {
    public void propertyChanged(PropertyChangeEvent e) {
        if (e.getNewValue() == SwingWorker.StateValue.DONE) {
            // do your code here that you want called when worker done
        }
    }
}
public void actionPerformed(ActionEvent arg0) {
    int returnVal = uploadChooser.showOpenDialog(Navigator.this);
    if(returnVal == JFileChooser.APPROVE_OPTION) {
        String pathToUpload = uploadChooser.getSelectedFile().getAbsolutePath();
        UploadUtil uploadIt = new UploadUtil(pathToUpload, chacha);
        uploadIt.addPropertyChangeListener(new UploadUtilListener());
        uploadIt.execute();
    }   
}