为什么线程在另一个开始执行时停止?

时间:2016-07-14 13:25:14

标签: java multithreading pool

我是Java并发API的新手,我已经搜索过,但没有找到我的问题的答案。

好吧,我有一个代码可以查找目录及其子目录中的每个文件,另一个代码可以复制每个匹配指定模式的文件。

我在一个名为 DirSearch Runnable 实现和一个名为 FileSearch Callable 实现中分离这些代码并提交它们使用 ExecutorService

这就是代码:

private boolean execute() {
    ExecutorService executor = Executors.newFixedThreadPool(threadsNumber);
    BlockingQueue<File> dirQueue = new LinkedBlockingQueue<>();
    BlockingQueue<File> fileQueue = new LinkedBlockingQueue<>(10000);

    boolean isFinished = false;

    try {
        for(int i = 0; i < dirThreads; i++) {
            executor.submit(new DirSearch(dirQueue, fileQueue, count, dirThreads);
        }

        count.incrementAndGet();
        dirQueue.add(baseDir);

        Future<Boolean> future = executor.submit(new FileSearch(filequeue, outputDirectory, filename));

        isFinished = future.get();
    } catch(ExecutionException | InterruptedException | RuntimeException ex) {
        ex.printStackTrace();
    } finally {
        executor.shutdownNow();
    }

    return isFinished;
}

...

private void copyFile(File in, File out) {
    Path inPath = Paths.get(in.getAbsolutePath());
    Path outPath = Paths.get(out.getAbsolutePath(), in.getName());

    try {
        main.updateCurrentLabel(outPath.toString());

        switch(mode) {
            case "1":
                Files.copy(inPath, outPath, StandardCopyOption.REPLACE_EXISTING);
                break;
            case "2":
                Files.move(inPath, outPath, StandardCopyOption.REPLACE_EXISTING);
                break;
            default:
                break;
        }

        main.updateCopiedLabel(String.valueOf(countCpFiles.incrementAndGet()));
    } catch(IOException ex) {
        ex.printStackTrace();
    }
}

...

private class DirSearch implements Runnable {

    ...

    @Override
    public void run() {
        try {
            File dir = dirQueue.take();

            while(dir != new File("")) {
                File[] elements = dir.listFiles();

                if(elements != null) {
                    for(File element : elements) {
                        if(element.isDirectory()) {
                            count.incrementAndGet();
                            dirQueue.put(element);
                        } else {
                            fileQueue.put(element);
                        }
                    }
                }

                if(count.decrementAndGet() == 0) {
                    end();
                }

                dir = dirQueue.take();
            }
        } catch(InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    ...

}

...

private class FileSearch implements Callable<Boolean> {

    ...

    @Override
    public Boolean call() {
        boolean isFinished = false;

        try {
            File file = fileQueue.take();

            while(file != new File("")) {
                incrementAnalyzed();
                String foundFile = file.getName().toLowerCase();

                if(foundFile.matches(filename.replace("?", ".?").replace("*", ".*?"))) {
                    copyFile(file, outputDirectory);
                }

                file = fileQueue.take();
            }

            isFinished = true;
        } catch(InterruptedException ex) {
            ex.printStackTrace();
        }

        return isFinished;
    }
}

问题是:当 FileSearch 开始复制文件时,其他线程( DirSearch )会停止,并且在复制完成之前不会查找任何新文件。为什么会这样?我做错了什么或者这不是正确的方法吗?

1 个答案:

答案 0 :(得分:-1)

我想到了两个可能的答案,我不能保证它们适用于您的具体情况: 1. Java VM只从CPU获取一个核心,这意味着它一次只能运行一个线程。 2.你的线程都使用相同的变量,这意味着一次只允许一个人真正操作它。对于此特定问题,请查找java关键字“synchronized”。 我想问题的根源往往是#1