我的代码库很大,所以我会尝试尽可能简洁。
我假设如果Runnable
在Thread
内完成执行,那么Thread
和Runnable
都将被销毁,因为里面的代码Runnable
是线性代码,也许是一些函数调用,但绝对没有循环。
问题是Thread
仍然有效,而我认为不应该。{/ p>
创建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";
}
}
代码中没有任何内容阻止执行,在这种情况下,特定字符串Processed
或Rotated
都打印到System.out
,之后特定Thread
仍然不会死。例如,即使Runnable
执行完毕,其中一个线程仍处于活动状态,其名称为:EST: RunnableProcessor("InputProcessor", "D:\OCR\renamed_input\682-converted.tiff")
。
线程的行为,超过两分钟测量,看起来很有意思:它遵循以下顺序:短时间运行,短时间监控,长时间运行,快速监控,短时间运行,等待时间过长,运行相对较短,等待时间很长,相对短暂的奔跑,等待(直到永恒?)。
任何人都可以帮忙弄明白到底发生了什么吗?
答案 0 :(得分:2)
您似乎正在使用执行程序服务。虽然它可以实现为每个任务创建新线程,但显然在您的情况下,使用线程池实现,该线程池保持线程等待新任务运行。根据{{3}},这样做是为了提高性能。
你不应该依赖执行者服务的内部运作。如果您需要在任务完成时收到通知,我建议您监控任务或/包装。
如果你想创建一个新的包装器并且似乎是轮询(线程状态),那么它可以很简单:
void run() {
innerRunner.run(); // the wrapped runner
doneFlag = true; // a boolean indicating the status
}
答案 1 :(得分:1)
您可能需要致电
Controller.getInstance().getExecutorService().shutdown();
Controller.getInstance().getExecutorService().awaitTermination();
关闭线程池。
答案 2 :(得分:0)
您使用创建固定数量线程的线程池。线程池重用已创建的线程来执行任务(Runnable, Callable
)。你不能显式销毁线程,因为线程是可管理的线程池。
正如你所说@Andrey Chaschev你应该叫它:
Controller.getInstance().getExecutorService().shutdown();
Controller.getInstance().getExecutorService().awaitTermination();
用于线程终止。