【问题标题】:Need help understanding threads in Java需要帮助理解 Java 中的线程
【发布时间】:2015-06-27 06:21:20
【问题描述】:

好的,我正在创建一个 Java 程序,用于下载游戏 Minecraft 的模组。我有以下课程可以完成所有下载并且工作正常。但是我有一个问题,即在 mod 下载时进度条没有更新(整个程序在下载时冻结)

经过大量研究,其他人似乎也有同样的问题,可以通过线程解决。

我只需要知道是否可以使用我现有的代码来执行此操作,还是我必须完全重新编写我的这个 java 类?

package com.anarcist.minemodloader;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.swing.JProgressBar;

public class modsDownloader {
    public static Boolean downloadMod(String mod, String saveLoc, JProgressBar progress){
        try {
            URL url = new URL(mod);
            //Set ProgressBar to 0%
            progress.setValue((int)0);
            //Open the Connection to the file
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            //Get filesize
            int filesize = connection.getContentLength();
            //Start reading at byte 0
            float totalDataRead = 0;

            BufferedInputStream in = new BufferedInputStream(connection.getInputStream());
            FileOutputStream fos = new FileOutputStream(saveLoc);
            BufferedOutputStream bout = new BufferedOutputStream(fos, 1024);

            byte[] data = new byte[1024];

            int i=0;
            while((i = in.read(data, 0, 1024)) >= 0){
                totalDataRead = totalDataRead + i;
                bout.write(data,0,i);
                float Percent=(totalDataRead * 100) / filesize;
                progress.setValue((int)Percent);
            }
            bout.close();
            in.close();
        }catch(Exception e){
            javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
            null,e.getMessage(), "Error",
            javax.swing.JOptionPane.DEFAULT_OPTION);
        }
        return true;
    }
}

此外,使用以下代码调用此函数/类:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    Object selectedObj = modsList.getSelectedValue();
    if (selectedObj instanceof modsListItem) {
        try {
            modsListItem selectedItem = (modsListItem) selectedObj;
            System.out.println(selectedItem.getValue());
            String fullName = selectedItem.getValue();
            String fileParts[] = fullName.split("/");
            String fileName = fileParts[fileParts.length - 1];
            String saveLoc = config.getModsFolder(true) + "/" + fileName;
            modsDownloader.downloadMod(selectedItem.getValue(), saveLoc, jProgressBar1);
        } catch (IOException ex) {
            Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
} 

【问题讨论】:

  • 嗯,很明显,你必须重写一些。阅读docs.oracle.com/javase/8/docs/api/javax/swing/SwingWorker.html
  • @JBNizet 我已经阅读了这篇文章,我希望我可以从doInBackground 函数中调用我的downloadMod 函数。我已经尝试过但不完全确定如何实现参数。
  • 就是这个想法,除了你可能不使用 doInBackground() 方法中的摆动组件(如进度条)。如果您需要帮助,请发布您尝试过的代码。
  • 扔掉,用ProgressMonitorInputStream.

标签: java multithreading


【解决方案1】:

这个方法调用是你的,在一个单独的线程中传递参数,但是return true语句是在主线程中执行的,所以虽然你的线程还没有结束他的工作,但它可能会返回true。

public static Boolean downloadModThread(String mod, String saveLoc, JProgressBar progress){
    new Thread(
        new Runnable(){
            public void run(){

                downloadMod(mod, saveLoc, progress);
            }
        }
    ).start();
    return true;

}

【讨论】:

    【解决方案2】:

    您可以使用 Swing invokeAndWait()invokeLater() invokeAndWait method in SwingUtilities 概念,如 FIFO 逻辑来执行特定工作并触发完成后的东西

    您可以使用 SwingWorker 逻辑来执行长时间运行的任务,还可以定期更新 UI

    参考How do I use SwingWorker in Java?

    参考Stop/cancel SwingWorker thread?

    【讨论】:

      猜你喜欢
      • 2014-08-29
      • 2012-09-01
      • 1970-01-01
      • 2013-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      相关资源
      最近更新 更多