首页 > 解决方案 > 在 Java 中运行 HTTPUrlConnection 的一些链接下载缓慢

问题描述

我是编程新手。我正在尝试为 Android 编写一个应用程序,它下载一个带有 HTML 链接的列表,并使用给定的链接来下载这些链接的内容。我将发布下载器的代码和日志。我的问题是:为什么有些链接需要大约 5 秒,而有些则需要 5 分钟?这不可能是网站的原因,因为当我在 Chrome 或其他浏览器中打开链接时,页面会立即加载。你们能帮帮我吗?

package com.example.newsreader;

import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MyRunnable implements Runnable {

    String result = "";
    String urlSource="";

    public MyRunnable(String urlSource){
        this.urlSource = urlSource;
    }

    @Override
    public void run() {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    result = "";
                    URL url = new URL(urlSource);
                    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setRequestMethod("GET");
                    InputStream inputStream = urlConnection.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

                    int data = inputStreamReader.read();

                    while (data !=-1) {
                        char current = (char) data;
                        result += current;
                        data = inputStreamReader.read();
                    }

                    inputStream.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        try{
            t1.join();
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    public String getResult(){
        return result;
    }
}

LOGDATA: 每个链接完成的时间

标签: javaandroidhttpurlconnectionrunnable

解决方案


您正在逐一读取数据,效率不高。相反,您应该创建 char 缓冲区并按小块读取数据。

也不要连接很多字符串,使用 StringBuilder,这样的事情使用更少的内存。

 public class MyRunnable implements Runnable {

    private final StringBuilder result = new StringBuilder();
    String urlSource="";
    private final char[] buffer = new char[512]; //allocating buffer

    public MyRunnable(String urlSource){
        this.urlSource = urlSource;
    }

    @Override
    public void run() {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    result.setLength(0); //clearing StringBuilder
                    URL url = new URL(urlSource);
                    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setRequestMethod("GET");
                    InputStream inputStream = urlConnection.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                    
                    // now reading not by 1 char, but by 512 for once
                    int i;
                    while ((i = inputStreamReader.read(buffer)) != -1) {
                       result.append(buffer, 0, i);
                    }

                    inputStreamReader.close(); //close reader instead of InputStream

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        try{
            t1.join();
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    public String getResult(){
        return result.toString(); //converting StringBuilder to String
    }
}

并且使用BufferedInputStream,它也增加了速度。

InputStreamReader inputStreamReader = new InputStreamReader(new BufferedInputStream(inputStream));

使用“https://www.google.com”进行的一些测试:

Simple run
time: 838 ms
run with char buffer
time: 264 ms
Run with char buffer and BufferedInputStream
time: 130 ms

推荐阅读