Java Swing 多线程加载图片(保证顺序一致)

所属分类: 软件编程 / java 阅读数: 16
收藏 0 赞 0 分享

大二的时候做的课程设计,图片管理器,当时遇到图片很多的文件夹,加载顺序非常慢。虽然尝试用多个Thread加载图片,却无法保证图片按顺序加载。直到今天学会了使用Callable接口和Future接口,于是心血来潮实现了这个功能。

废话不多说,看代码。

多线程加载图片(核心):

package com.lin.imagemgr;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import javax.swing.ImageIcon;
import javax.swing.JLabel;

import net.coobird.thumbnailator.Thumbnails;

public class ImageMgr {
 private static ImageMgr instance = new ImageMgr();
 private ImageMgr() {}
 public static ImageMgr getInstance() {
  return instance;
 }

 //线程池
 private ExecutorService executor = Executors.newFixedThreadPool(8);

 public List<JLabel> loadImages(String path) {
  List<JLabel> images = new ArrayList<>();
  File file = new File(path);
  if (!file.isDirectory()) {
   throw new RuntimeException("need directory!");
  }
  File[] files = file.listFiles(new FilenameFilter() {

   @Override
   public boolean accept(File dir, String name) {
    //thumbnail只支持jpg??
    if (name.endsWith(".jpg")) {
     return true;
    }
    return false;
   }
  });

  //并发加载图片,并使用Future保存加载结果
  List<Future<MyLabel>> futures = new ArrayList<>();
  for (final File f : files) {
   Future<MyLabel> future = executor.submit(() -> {
    return new MyLabel(f.getName(), f.getAbsolutePath());
   });
   futures.add(future);
  }

  //等待所有并发加载返回结果
  try {
   for (Future<MyLabel> future : futures) {
    MyLabel icon = future.get();
    images.add(icon);
   }
  } catch (InterruptedException e) {
   e.printStackTrace();
  } catch (ExecutionException e) {
   e.printStackTrace();
  }

  //Java8使用stream API 进行排序
  List<JLabel> sortedList = images.stream().sorted().collect(Collectors.toList());

  return sortedList;
 }

 //继承JLabel并实现Comparable接口,从而对JLabel进行排序
 private static class MyLabel extends JLabel implements Comparable<MyLabel>{
  private static final long serialVersionUID = 1L;
  private String fileName;

  public MyLabel(String fileName, String fullPath) {
   this.fileName = fileName;
   //使用thumbnailator生成缩略图
   try {
    BufferedImage bufferedImage = Thumbnails.of(fullPath) 
    .size(100, 120)
    .asBufferedImage();
    setIcon(new ImageIcon(bufferedImage));
    setPreferredSize(new Dimension(100, 120));
   } catch (IOException e) {
    e.printStackTrace();
   }
  }

  @Override
  public int compareTo(MyLabel o) {
   int result = this.fileName.compareTo(o.fileName);
   return result;
  }


 }

}

Swing界面:

package com.lin.imagemgr;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

public class MainFrame extends JFrame{
 private static final long serialVersionUID = 1L;
 private JTextField pathField;
 private JButton showBtn;
 private JPanel contentPanel;

 public void init() {
  JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
  topPanel.setPreferredSize(new Dimension(800, 40));
  pathField = new JTextField(50);
  showBtn = new JButton("显示图片");
  topPanel.add(pathField);
  topPanel.add(showBtn);
  getContentPane().add(BorderLayout.NORTH, topPanel);
  contentPanel = new JPanel();
  contentPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
  contentPanel.setPreferredSize(new Dimension(750, 1800));
  JScrollPane jsp = new JScrollPane(contentPanel);
  getContentPane().add(BorderLayout.CENTER, jsp);

  showBtn.addActionListener((e) -> {
   try {
    loadImages();
   } catch (Exception ex) {
    ex.printStackTrace();
   }
  });

  setSize(800, 650);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  setLocationRelativeTo(null);
  setVisible(true);
 }

 public void loadImages() {
  contentPanel.removeAll();
  String path = pathField.getText();
  long start = System.currentTimeMillis();
  List<JLabel> images = ImageMgr.getInstance().loadImages(path);
  for (JLabel label :images) {
   contentPanel.add(label);
  }
  contentPanel.updateUI();
  long end = System.currentTimeMillis();
  System.out.println("加载需要" + (end - start) + "毫秒!");

 }

 public static void main(String[] args) {
  new MainFrame().init();
 }

}

运行结果

这里写图片描述

在我的电脑上,加载92张图片并渲染到界面上,总共花了1568毫秒。大家可以找一个图片很多的文件夹,尝试加载大量图片的情况。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

Java数据类型的规则

这篇文章主要介绍了Java数据类型的规则的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

Spring整合TimerTask实现定时任务调度

这篇文章主要介绍了Spring整合TimerTask实现定时任务调度的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

详解SpringMVC使用MultipartFile实现文件的上传

本篇文章主要介绍了SpringMVC使用MultipartFile实现文件的上传,本地的文件上传到资源服务器上,比较好的办法就是通过ftp上传。这里是结合SpringMVC+ftp的形式上传的,有兴趣的可以了解一下。
收藏 0 赞 0 分享

SpringMVC上传文件的三种实现方式

本篇文章主要介绍了SpringMVC上传文件的三种实现方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

微信公众帐号开发-自定义菜单的创建及菜单事件响应的实例

本篇文章主要介绍了微信公众帐号开发-自定义菜单的创建及菜单事件响应的实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
收藏 0 赞 0 分享

浅析Java中的继承与组合

本文将介绍组合和继承的概念及区别,并从多方面分析在写代码时如何进行选择。文中通过示例代码介绍的很详细,有需要的朋友可以参考借鉴,下面来一起看看吧。
收藏 0 赞 0 分享

利用反射获取Java类中的静态变量名及变量值的简单实例

下面小编就为大家带来一篇利用反射获取Java类中的静态变量名及变量值的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

java启动线程的3种方式对比分析

这篇文章主要为大家对比分析了java启动线程的3种方式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

SpringMVC上传和解析Excel方法

这篇文章主要介绍了SpringMVC上传和解析Excel方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

JAVA中String类与StringBuffer类的区别

这篇文章主要为大家详细介绍了JAVA中String类与StringBuffer类的区别,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享
查看更多