用Java下载文件。多线程,这行得通吗?

天天见闻 天天见闻 2023-03-15 综合 阅读: 100
摘要:

如何解决用Java下载文件。多线程,这行得通吗??

意见建议:

  • 使用SwingWorker进行后台线程工作。
  • 在您的SwingWorker内部,通过设置其进度“ bound”属性setProgress(int progress)。该值应在1到100之间。
  • 不要让您的SwingWorker /文件下载器拥有JProgressBar或任何Swing组件。
  • 将Propertychangelistener添加到您的SwingWorker,并监视progress属性中的更改。
  • 切勿将您的Swing字段(或大多数和所有字段)公开。限制访问,而是通过方法更改对象状态。
  • 阅读Swing中的并发教程以获取必要的详细信息。

例如,下面的代码是一个简单的简化,不下载任何文件,但是应该可以使您了解:

import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.Propertychangelistener;
import java.util.Random;

import javax.swing.*;

public class Initial {

   static AtomFrame atomLauncher;

   public static void main(String[] args) {

      atomLauncher = new AtomFrame();
      atomLauncher.start();

      System.out.println(Integer.MAX_VALUE);

      final Download theDownload = new Download();
      theDownload.addPropertychangelistener(new Propertychangelistener() {

         @Override
         public void propertyChange(PropertyChangeEvent pcEvt) {
            if ("progress".equals(pcEvt.getPropertyName())) {
               int progress = theDownload.getProgress();
               atomLauncher.setProgress(progress);
            }
         }
      });

      theDownload.execute();
   }

}

class AtomFrame extends JFrame {

   // ********* should be private!
   private JProgressBar progressBar;

   private static final long serialVersionUID = 4010489530693307355L;

   public static void main(String[] args) {
      AtomFrame testFrame = new AtomFrame();
      testFrame.start();
   }

   public void setProgress(int progress) {
      progressBar.setValue(progress);
   }

   public AtomFrame() {
      initializeComponents();
   }

   public void initializeComponents() {
      this.setSize(400, 400);
      this.setLocationRelativeto(null);
      this.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
      this.setTitle("Atom Launcher");
      this.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

      progressBar = new JProgressBar();
      this.add(progressBar);

      // this.pack();
   }

   public void start() {
      this.setVisible(true);
   }

   public void close() {
      this.dispose();
   }
}

class Download extends SwingWorker {
   private static final long SLEEP_TIME = 300;
   private Random random = new Random();

   @Override
   protected Void doInBackground() throws Exception {
      int myProgress = 0;
      while (myProgress < 100) {
         myProgress += random.nextInt(10);
         setProgress(myProgress);
         try {
            Thread.sleep(SLEEP_TIME);
         } catch (InterruptedException e) {}
      }
      return null;
   }
}

解决方法

首先,每个人都需要知道我对Java编码还比较陌生。更准确地说,我是面向对象编程的新手。


问题。

我试图创建一个下载类来更新进度条,以显示其进度。可能还有其他决定,我决定在以后进行更新。

目前的问题是,在我看来,这不起作用。我可以在“主要”方法上做任何我想做的事情,而且GUI仍然响应迅速。根据我过去的编程经验,除非我对GUI进行线程化,否则这是不可能的。为什么是这样?

既然可以了,这样可以吗?


主班

package atomicElectronics;

import java.io.IOException;

import atomicElectronics.physical.AtomFrame;
import atomicElectronics.utility.Download;

public class Initial {

    static AtomFrame atomLauncher;

    public static void main(String[] args) {

        atomLauncher = new AtomFrame();
        atomLauncher.start();

        System.out.println(Integer.MAX_VALUE);

        Download theDownload = new Download();
        theDownload.fileProgressBar(atomLauncher.progressBar);
        try {
            theDownload.exicute("http://download.videolan.org/pub/videolan/vlc/last/win64/vlc-2.1.3-win64.exe","C:\\Users\\TrinaryAtom\\AppData\\Roaming");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // TODO Add Download Methods
        // theDownload.updateBarTotal(JProgressBar);
        // theDownload.updateLabelSpeed(String);
        // theDownload.updateLabelTotal(String);
        // theDownload.addFile(File);
        // theDownload.addFiles(Files);
    }

}

类AtomFrame

package atomicElectronics.physical;

import javax.swing.JFrame;
import java.awt.FlowLayout;
import javax.swing.JProgressBar;

public class AtomFrame extends JFrame{

    public JProgressBar progressBar;

    private static final long serialVersionUID = 4010489530693307355L;

    public static void main(String[] args){
        AtomFrame testFrame = new AtomFrame();
        testFrame.start();
    }

    public AtomFrame(){
        initializeComponents();
    }

    public void initializeComponents(){
        this.setSize(400,400);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setTitle("Atom Launcher");
        this.setLayout(new FlowLayout(FlowLayout.CENTER,5,5));

        progressBar = new JProgressBar();
        this.add(progressBar);

        //this.pack();
    }

    public void start() {
        this.setVisible(true);
    }

    public void close() {
        this.dispose();
    }
}

类下载

package atomicElectronics.utility;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.swing.JProgressBar;

public class Download {

    private static final int BUFFER_SIZE = 4096;
    private JProgressBar fileProgressBar;

    public Download() {
    }

    public void fileProgressBar(JProgressBar fileBar) {
        fileProgressBar = fileBar;
    }

    public void exicute(String fileURL,String saveDir) throws IOException  {

        URL url = new URL(fileURL);
        HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
        int responseCode = httpConn.getResponseCode();

        // always check HTTP response code first
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String fileName = "";
            String disposition = httpConn.getHeaderField("Content-Disposition");
            String contentType = httpConn.getContentType();
            double contentLength = httpConn.getContentLength();

            if (disposition != null) {
                // extracts file name from header field
                int index = disposition.indexOf("filename=");
                if (index > 0) {


          fileName = disposition.substring(index + 9,disposition.length());
            }
        } else {
            // extracts file name from URL
            fileName = fileURL.substring(fileURL.lastIndexOf("/") + 1,fileURL.length());
        }

        System.out.println("Content-Type = " + contentType);
        System.out.println("Content-Disposition = " + disposition);
        System.out.println("Content-Length = " + contentLength);
        System.out.println("fileName = " + fileName);

        // opens input stream from the HTTP connection
        InputStream inputStream = httpConn.getInputStream();
        String saveFilePath = saveDir + File.separator + fileName;

        // opens an output stream to save into file
        FileOutputStream outputStream = new FileOutputStream(saveFilePath);

        double totalRead = 0;
        int bytesRead = -1;
        byte[] buffer = new byte[BUFFER_SIZE];
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer,bytesRead);
            totalRead += bytesRead;
            System.out.println((totalRead / contentLength) * 100);
            fileProgressBar.setValue((int)((totalRead / contentLength) * 100));
        }

        outputStream.close();
        inputStream.close();

        System.out.println("File downloaded");
    } else {
        System.out.println("No file to download. Server replied HTTP code: " + responseCode);
    }
    httpConn.disconnect();

}

}

其他相关
常用语言的线程模型(Java、go、C++、python3) | 京东云技术团队

常用语言的线程模型(Java、go、C++、python3) | 京东云技术团队

作者: 天天见闻 时间:2023-10-17 阅读: 58
背景知识软件如何驱动硬件?硬件需要相关的驱动程序才能运行,驱动程序安装在操作系统内核中。编写一个程序A后,A程序要操作硬件操作,首先需要进行系统调用,然后内核寻找相应的驱动程序来驱动硬件。驱动程序如何运行硬件?驱动程序作为硬件和操作系统之间的媒介,可以将与操作系统相关的命令翻译成硬件能够识别的电信号,同时,驱动程序还可以将硬件电信号转换为操作系统可以识别的命令。进程、轻量级进程、线程关系由于一个进程执行的空间不同,它被分为内核线程和用户进程,所有这些都称为内核线程,因为它没有虚拟地址空间。当创建一个新的用户进程时,分配一个新的虚拟地址空间,其中不同用户进程之间的资源被分离。创建新流程需要耗费大量资源,而且流程之间切换的成本也很高,因此引入了轻型流程。轻量化在本质上也是对内核线程的上层是抽象的,可以在不同的轻量级进程之间共享一些资源,但是由于轻量级进程本质上是内核线程,所以进行轻量级线程之间的切换需要进行系统调用,成本也很昂贵。内核本质上只能感知进程的存在,就像不同语言的多线程技术一样,是基于用户进程创建的线程库,线程本身不是参与处理器竞争,而是其所属的用户进程参与处理器的竞争。...
无法报告状态600秒钟。杀人!报告Hadoop的进度

无法报告状态600秒钟。杀人!报告Hadoop的进度

作者: 天天见闻 时间:2023-03-15 阅读: 69
如何解决无法报告状态600秒钟。这个问题是一个做错误Hadoop中0.20由此将调用context.setStatus()和context.progress()不被报告给底层框架。有可用的补丁程序,因此更新到较新版本的Hadoop应该可以解决此问题。但是, 我不想增加hadoop杀死不报告进度的任务之前的默认时间 ,即。相反,我想无论是使用定期汇报工作进度context.progress(),context.setStatus或者context.getCounter.increment或者类似的东西。但是,在默认时间后,该作业仍被终止。我是否以错误的方式使用上下文?...
Java多线程环境中对象的序列化

Java多线程环境中对象的序列化

作者: 天天见闻 时间:2023-03-14 阅读: 85
直到不再有任何线程在Counter上运行了?如果Counter的同步不使用固有锁,您的应用程序还需要使用其他锁定来锁定更新。获取锁而又没有死锁风险的问题也很成问题。目标是从另一个线程定期保存其状态(通过序列化):class Counter Serializable private count;public synchronized ...
最新idm6.41下载器最新版2023中文特别版怎么使用?真可以速度提升500%?

最新idm6.41下载器最新版2023中文特别版怎么使用?真可以速度提升500%?

作者: 天天见闻 时间:2022-12-05 阅读: 188
Internet Download Manager,全球最佳下载利器。Internet Download Manager 6.41 是一款Windows 平台功能强大的多线程下载工具,国外非常受欢迎。支持断点续传,支持嗅探视频音频,接管所有浏览器,具有站点抓取、批量下载队列、计划任务下载,自动识别文件名、静默下载、网盘下载支持等功能。...
锐龙5可战i9!锐龙7 7700X/锐龙5 7600X评测:当代最香2000元处理器

锐龙5可战i9!锐龙7 7700X/锐龙5 7600X评测:当代最香2000元处理器

作者: 天天见闻 时间:2022-10-02 阅读: 290
锐龙5可战i9!锐龙7 7700X/锐龙5 7600X评测:当代最香2000元处理器 一、前言:锐龙5 7600X直面i5-12600K 在Zen4发布之前,最香的2000元处理器当属i5-12600K。面对它,AMD承受了巨大的压力,特别是锐龙7 5800X一再降价以应对挑战。当然,这并不是锐龙7 5800X的问题,因为在此之前,它已经战过两代酷睿处理器了。 2022年9月26日,Zen4构架的锐龙7000X系列处理器正式解禁,我们也给大家同步带来了锐龙9 7900X和锐龙9 7950X两款顶级高端锐龙处理器的首发评测,在它们面前,Intel最强的i9-12900K已完全不是对手。...
鸿蒙和安卓的关系是什么?关于鸿蒙系统的这5大疑问有答案了

鸿蒙和安卓的关系是什么?关于鸿蒙系统的这5大疑问有答案了

作者: 天天见闻 时间:2022-02-21 阅读: 1799
华为2日发布包括智能手表、平板电脑在内的多款搭载Har-monyOS2(鸿蒙)的新产品。旗下手机、平板电脑等多款设备将陆续启动Harmon-yOS2升级。为不同设备的智能化、互联与协同提供统一的语言。让多设备应用开发更加简单,分布式智能应用能够在不同设备中快速流转,智慧屏用户则需要通过花粉俱乐部APP,依次进入论坛-软件专区-升级尝鲜-华为智慧屏内测招募帖“...
我来说两句

年度爆文