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

网友投稿 374 2023-03-06


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 loadImages(String path) {

List 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> futures http://= new ArrayList<>();

for (final File f : files) {

Future future = executor.submit(() -> {

return new MyLabel(f.getName(), f.getAbsolutePath());

});

futures.add(future);

}

//等待所有并发加载返回结果

try {

for (Future future : futures) {

MyLabel icon = future.get();

images.add(icon);

}

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

//Java8使用stream API 进行排序

List sortedList = images.stream().sorted().collect(Collectors.toList());

return sortedList;

}

//继承JLabel并实现Comparable接口,从而对JLabel进行排序

private static class MyLabel extends JLabel implements Comparable{

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);

setDefaulthttp://CloseOperation(JFrame.EXIT_ON_CLOSE);

setLocationRelativeTo(null);

setVisible(true);

}

public void loadImages() {

contentPanel.removeAll();

String path = pathField.getText();

long start = System.currentTimeMillis();

List 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毫秒。大家可以找一个图片很多的文件夹,尝试加载大量图片的情况。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:api接口怎么写文档(api接口文档怎么用)
下一篇:Java实现按照大小写字母顺序排序的方法
相关文章

 发表评论

暂时没有评论,来抢沙发吧~