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

来源:互联网 发布:周振兴 mysql 编辑:程序博客网 时间:2024/05/18 00:39

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

大二的时候做的课程设计,图片管理器,当时遇到图片很多的文件夹,加载顺序非常慢。虽然尝试用多个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毫秒。大家可以找一个图片很多的文件夹,尝试加载大量图片的情况。

原创粉丝点击