Java中多线程下载图片并压缩能提高效率吗

  

Java中多线程下载图片并压缩能提高效率吗

在Java中使用多线程下载图片并压缩,可以提高程序的效率,因为多线程能够充分利用CPU的多核心,同时多个线程并行执行任务,从而加速程序的处理速度。下面详细讲解Java中多线程下载图片并压缩的完整攻略。

步骤一:下载图片

首先需要使用Java的URL和HttpURLConnection类实现图片下载功能,代码如下:

String imageUrl = "http://example.com/example.jpg";
URL url = new URL(imageUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
InputStream inputStream = conn.getInputStream();

其中,imageUrl为图片的URL地址,使用URL类创建一个URL对象,然后使用HttpURLConnection打开连接,设置请求方法为GET,连接超时时间为5秒钟,调用getInputStream方法获取输入流。

步骤二:保存图片

下载图片后,需要将其保存到本地,Java的FileOutputStream类可以完成该任务,代码如下:

String fileName = "example.jpg";
File file = new File(fileName);
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[4096];
int len = -1;
while ((len = inputStream.read(buffer)) != -1) {
    fos.write(buffer, 0, len);
}
fos.close();
inputStream.close();

其中,fileName为保存图片的文件名,使用File类创建一个文件对象,然后使用FileOutputStream类创建一个输出流,将图片数据写入到文件中,最后关闭流。

步骤三:压缩图片

下载并保存图片后,需要对其进行压缩,Java的ImageIO类可以完成该任务,代码如下:

String compressedFileName = "compressed_example.jpg";
File compressedFile = new File(compressedFileName);
BufferedImage image = ImageIO.read(file);
BufferedImage compressedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = compressedImage.createGraphics();
g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
g.dispose();
ImageIO.write(compressedImage, "jpg", compressedFile);

其中,compressedFileName为压缩后的文件名,使用File类创建一个文件对象,然后使用ImageIO类读取下载的原始图片数据,创建一个新的BufferedImage对象代表压缩后的图片。使用Graphics2D类,将原始图片缩放至指定大小,最后使用ImageIO类将压缩后的图片保存到文件中。

步骤四:多线程下载并压缩图片

对于批量下载图片的场景,可以使用多线程下载和压缩,Java的Executor框架可以很好的实现。代码如下:

ExecutorService executorService = Executors.newFixedThreadPool(4);
List<String> imageUrls = Arrays.asList("http://example.com/example1.jpg", "http://example.com/example2.jpg", "http://example.com/example3.jpg", "http://example.com/example4.jpg");
for (String url : imageUrls) {
    executorService.execute(() -> {
        try {
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            InputStream inputStream = conn.getInputStream();

            String fileName = url.substring(url.lastIndexOf("/") + 1);
            File file = new File(fileName);
            FileOutputStream fos = new FileOutputStream(file);
            byte[] buffer = new byte[4096];
            int len = -1;
            while ((len = inputStream.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            fos.close();
            inputStream.close();

            String compressedFileName = "compressed_" + fileName;
            File compressedFile = new File(compressedFileName);
            BufferedImage image = ImageIO.read(file);
            BufferedImage compressedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
            Graphics2D g = compressedImage.createGraphics();
            g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
            g.dispose();
            ImageIO.write(compressedImage, "jpg", compressedFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
    });
}
executorService.shutdown();

其中,使用ExecutorService创建一个线程池,使用Arrays.asList方法创建一个包含多个图片URL地址的列表。

在使用ExecutorService执行任务时,可以使用lambda表达式的形式,将下载和压缩图片的代码封装在Runnable接口中。

最后调用ExecutorService的shutdown方法关闭线程池即可。

示例一:多线程下载并压缩图片

对于一个100张图片的批量下载和压缩的任务,使用单线程需要100次I/O操作,而使用4个线程下载并压缩图片,每个线程只需要下载25张图片,所以需要进行25次I/O操作,程序执行时间会大大缩短。

示例二:多线程下载并压缩网站上的图片

对于一个网站上的图片批量下载和压缩的任务,可以利用Jsoup库爬取网站图片的URL,然后使用多线程下载和压缩。代码如下:

String url = "http://example.com";
Document doc = Jsoup.connect(url).get();
Elements images = doc.select("img[src~=(?i)\\.(png|jpe?g|gif)]");
List<String> imageUrls = new ArrayList<>();
for (Element image : images) {
    String imageUrl = image.absUrl("src");
    imageUrls.add(imageUrl);
}

ExecutorService executorService = Executors.newFixedThreadPool(4);
for (String imageUrl : imageUrls) {
    executorService.execute(() -> {
        // 略
    });
}
executorService.shutdown();

其中,使用Jsoup库访问指定网站,然后使用CSS选择符,选取网站上所有的图片元素,并获取其src属性的值,作为要下载的图片URL地址。

最后使用多线程进行图片的下载和压缩。

综上所述,Java中使用多线程下载图片并压缩可以提高程序的效率,特别在处理大量图片时,可以显著减少程序的执行时间。

相关文章