1

我的代码库很大,所以我会尽量把它放在这里。

我的假设是,如果 a在 aRunnable内完成执行Thread,那么 theThread和 theRunnable都将被销毁,因为其中的代码Runnable是线性代码,也许是一些函数调用,但绝对没有循环。

问题是Thread确实仍在运行,而我认为它不应该。

创建RunnableProcessor

Controller.getInstance().getNamedThreadFactory().addThreadName("EST: " + runnableProcessor.toString());
Controller.getInstance().getExecutorService().execute(runnableProcessor);

RunnableProcessor班级:

public class RunnableProcessor<T> implements Runnable {
    private final Processor<T> processor;
    private final T object;

    public RunnableProcessor(final Processor<T> processor, final T object) {
        this.processor = processor;
        this.object = object;
    }

    @Override
    public void run() {
        processor.process(object);
    }

    @Override
    public String toString() {
        return "RunnableProcessor(\"" + processor + "\", \"" + object.toString() + "\")";
    }
}

这样的一个例子Processor,即InputProcessor

public class InputProcessor implements Processor<File> {
    private static final String PDF = "pdf";

    @Override
    public void process(File file) {
        if (new CustomPath(file).getExtension().equalsIgnoreCase(PDF)) {
            processPdf(file);
        }
        else {
            processImage(file);
        }
    }

    private void processPdf(final File file) {
        System.out.println("Processing " + file.toString());
        FileEditor.convert(file);
        Utils.move(file.toPath(), new File(Controller.DONE_URL + File.separator + file.getName()).toPath());
        System.out.println("Processed");
    }

    private void processImage(final File file) {
        //Skew detection
        System.out.println("Rotating " + file.toString());
        SkewDetector skewDetector = new SkewDetector(file);
        File rotatedFile = skewDetector.detect();
        Utils.move(rotatedFile.toPath(), new File(Controller.ROTATED_INPUT_URL + File.separator + rotatedFile.getName()).toPath());
        System.out.println("Rotated");
    }

    @Override
    public String toString() {
        return "InputProcessor";
    }
}

代码中的任何内容都不会阻止执行,即在这种情况下,特定的字符串ProcessedRotated都被打印到System.out,之后特定的Thread仍然没有死。这是例如其中一个线程仍然处于活动状态,即使执行Runnable完成,名称是:EST: RunnableProcessor("InputProcessor", "D:\OCR\renamed_input\682-converted.tiff")

线程的行为,经过两分钟的测量,似乎很有趣:它遵循以下顺序:短时间运行,短时间被监控,长时间运行,快速监控,短时间运行,非常长的等待,相对短的运行,非常长的等待,相对短运行,等待(直到永恒?)。

谁能帮忙弄清楚到底发生了什么?

4

3 回答 3

2

您似乎正在使用执行程序服务。虽然可以实现它为每个任务创建新线程,但显然在您的情况下,它是使用线程池实现的,该线程池使线程等待新任务运行。根据文档,这样做是为了获得更好的性能。

无论如何,您不应该依赖 executor 服务的内部工作。如果您需要在任务完成时收到通知,我建议您监视任务或/a 包装器。

如果您想创建一个新的包装器并且似乎正在轮询(线程状态),它可以很简单:

void run() {
    innerRunner.run();  // the wrapped runner
    doneFlag = true;    // a boolean indicating the status
}
于 2013-11-13T08:38:06.793 回答
1

您可能需要致电

Controller.getInstance().getExecutorService().shutdown();
Controller.getInstance().getExecutorService().awaitTermination();

关闭你的线程池。

于 2013-11-13T08:36:56.737 回答
0

您使用创建固定数量线程的线程池。线程池重用创建的线程来执行任务(Runnable, Callable)。您不能显式销毁线程,因为线程是可管理的线程池。

正如你所说的@Andrey Chaschev,你应该称之为:

Controller.getInstance().getExecutorService().shutdown();
Controller.getInstance().getExecutorService().awaitTermination();

用于线程终止。

于 2013-11-13T08:43:51.740 回答