Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用ExecutorService在多个线程中向ConcurrentHashMap正确添加元素_Java_Multithreading_Executorservice_Concurrenthashmap - Fatal编程技术网

Java 如何使用ExecutorService在多个线程中向ConcurrentHashMap正确添加元素

Java 如何使用ExecutorService在多个线程中向ConcurrentHashMap正确添加元素,java,multithreading,executorservice,concurrenthashmap,Java,Multithreading,Executorservice,Concurrenthashmap,我正在尝试使用多个线程将图像从某个文件夹加载到ConcurrentHashMap以节省时间。不幸的是,一些线程在尝试加载图像并将其放入我的地图时“卡住了”。因此,当调用shutdown()时,即使某些线程没有执行它们的任务,程序也会更进一步。当我将ExecutorService线程pule设置为1时,一切正常,但我浪费了大量时间等待加载所有图像。在我看来,存在一些争用问题,但据我所知,ConcurrentHashMap对于多线程操作是安全的。我还是一个初学者,所以请让我了解问题出在哪里,我做得不

我正在尝试使用多个线程将图像从某个文件夹加载到ConcurrentHashMap以节省时间。不幸的是,一些线程在尝试加载图像并将其放入我的地图时“卡住了”。因此,当调用shutdown()时,即使某些线程没有执行它们的任务,程序也会更进一步。当我将ExecutorService线程pule设置为1时,一切正常,但我浪费了大量时间等待加载所有图像。在我看来,存在一些争用问题,但据我所知,ConcurrentHashMap对于多线程操作是安全的。我还是一个初学者,所以请让我了解问题出在哪里,我做得不好。 代码如下:

public abstract class ImageContainer {

private final static Map<String, BufferedImage> imageMap = loadImages();
private static long loadingTime;

public static Map<String, BufferedImage> loadImages() {

    loadingTime = System.currentTimeMillis();
    ConcurrentHashMap<String, BufferedImage> imageMap = new ConcurrentHashMap<>();
    ExecutorService es = Executors.newFixedThreadPool(5);
    File imageDirectory = new File("Images/");
    if (!imageDirectory.isDirectory()) {
        System.out.println("Image directory error");
    }
    File[] files = imageDirectory.listFiles();
    if (files != null) {
        for (File file : files) {
            if (file.isFile()) {
                es.submit(new Runnable(){
                    @Override
                    public void run() {
                        try{
                            if(file.getAbsolutePath().contains(".jpg")) {
                                imageMap.put(file.getName().replace(".jpg",""),ImageIO.read(file));
                            }
                            else if (file.getAbsolutePath().contains(".png")) {
                                imageMap.put(file.getName().replace(".png",""),ImageIO.read(file));
                            }
                        }
                        catch (IOException e)
                        {
                            System.out.println("Cannot load image");
                        }
                    }
                });
            }
        }
    }
    else
    {
        System.out.println("Image folder empty!");
    }

    es.shutdown();
    try {
        if(!es.awaitTermination(5L, TimeUnit.SECONDS)) {
            System.out.println("Images did not load successfully!");
            es.shutdownNow();
        }
        loadingTime = System.currentTimeMillis() - loadingTime;
    }
    catch(InterruptedException e) {
        System.out.println("Loading images interrupted!");
    }
    System.out.println(imageMap.size());
    return imageMap;
}
};
公共抽象类ImageContainer{
私有最终静态映射imageMap=loadImages();
私有静态长加载时间;
公共静态地图加载图像(){
loadingTime=System.currentTimeMillis();
ConcurrentHashMap imageMap=新的ConcurrentHashMap();
Executors服务es=Executors.newFixedThreadPool(5);
File imageDirectory=新文件(“Images/”);
如果(!imageDirectory.isDirectory()){
System.out.println(“图像目录错误”);
}
File[]files=imageDirectory.listFiles();
如果(文件!=null){
用于(文件:文件){
if(file.isFile()){
es.submit(新的Runnable(){
@凌驾
公开募捐{
试一试{
如果(file.getAbsolutePath()包含(“.jpg”)){
imageMap.put(file.getName().replace(“.jpg”,”),ImageIO.read(file));
}
else if(file.getAbsolutePath()包含(“.png”)){
imageMap.put(file.getName().replace(“.png”,”),ImageIO.read(file));
}
}
捕获(IOE异常)
{
System.out.println(“无法加载图像”);
}
}
});
}
}
}
其他的
{
System.out.println(“图像文件夹为空!”);
}
es.shutdown();
试一试{
如果(!es.等待终止(5L,时间单位秒)){
System.out.println(“图像未成功加载!”);
es.shutdownNow();
}
loadingTime=System.currentTimeMillis()-loadingTime;
}
捕捉(中断异常e){
System.out.println(“加载图像中断!”);
}
System.out.println(imageMap.size());
返回图像地图;
}
};

问题很可能与
ConcurrentHashMap
无关。每次您
某物放入映射中时,没有其他线程能够同时
放入
。因此,一些线程可能必须等待另一个线程完成
put
,但这不会导致任何争用条件

我在我的机器上执行了你的代码,一切正常。(无错误消息,打印加载图像的数量)。也许你的计算机加载图像的速度不如我的快,因此,
等待终止
超时

就我所知,我不知道你的方法(用多线程加载图像)是否是个好主意。您的硬盘驱动器(或SSD)将成为瓶颈,您的线程将最终等待硬盘驱动器(语句
ImageIO.read
)。
另外,旋转执行器服务(即启动新线程)并不便宜,因此可能不使用多线程更好。特别是因为您只需要加载一次图像(之后,图像将缓存在地图中),所以加速可能永远不会显著。我会考虑顺序加载图像。

< P>这个问题很可能与<代码> CONCURNESHASMAP 无关。每次您
某物放入映射中时,没有其他线程能够同时
放入
。因此,一些线程可能必须等待另一个线程完成
put
,但这不会导致任何争用条件

我在我的机器上执行了你的代码,一切正常。(无错误消息,打印加载图像的数量)。也许你的计算机加载图像的速度不如我的快,因此,
等待终止
超时

就我所知,我不知道你的方法(用多线程加载图像)是否是个好主意。您的硬盘驱动器(或SSD)将成为瓶颈,您的线程将最终等待硬盘驱动器(语句
ImageIO.read
)。
另外,旋转执行器服务(即启动新线程)并不便宜,因此可能不使用多线程更好。特别是因为您只需要加载一次图像(之后,图像将缓存在地图中),所以加速可能永远不会显著。我会考虑顺序加载图像。

IMAIIO是相当慢的并且非常I/O密集型的,所以添加很多线程通常对典型的PCs.没有帮助。你确信你不需要为等待终止超时添加大量的数字吗? 另一种选择是对线程池使用长度有限的LinkBlockingQueue,这样当使用者速度较慢时,主应用程序线程的速度就会减慢。这意味着结束时的延时5L秒是现实的,可以允许正在进行的呼叫结束

请参阅JDK source以了解newFixedThreadPool(n),在LinkedBlockingQueue()的构造函数中尝试qSize=2或3 x nthreads

publicstaticexecutorservice newFixedThreadPool(int-nThreads){
返回新的ThreadPoolExecutor(第n个线程,第n个线程,
0L,时间单位为毫秒,
新建LinkedBlockingQueue());
}

ImageIO速度非常慢,而且I/O非常密集,因此添加许多线程通常对典型的应用程序没有帮助
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}