【发布时间】:2021-05-08 05:05:49
【问题描述】:
我有上下文,可以用来产生预测。基于上下文进行预测的算法不是我的问题的一部分。但它很耗时,所以我将它从主线程中移出。在任何时候上下文都可能改变。发生这种情况时,应用程序应使用新输入重新启动预测生成。与旧上下文相关的预测将变为无效,因此应中断其计算。
现在我使用代码:
public class BackgroundTasksManager {
public static final BackgroundTasksManager shared = new BackgroundTasksManager();
private ExecutorService conceptResultsExecutor = null;
private BackgroundTasksManager() { }
public void startConceptResultsCalculation(ConceptResultsCalculationInput input,
Consumer<ConceptResultsCalculationOutput> callback) {
ThreadGroup callbackGroup = Thread.currentThread().getThreadGroup();
if (conceptResultsExecutor != null)
conceptResultsExecutor.shutdownNow();
conceptResultsExecutor = Executors.newSingleThreadExecutor();
conceptResultsExecutor.submit(() -> {
ConceptResultsCalculationOutput output = ConceptResultsCombinator.possbileResults(input);
Thread callbackThread = new Thread(callbackGroup, () -> callback.accept(output));
callbackThread.start();
});
}
所以,当我需要开始预测计算时,我关闭了旧的 Executor 并创建了一个新的。此解决方案有效,但它是否有效,或者隐藏了一些危险的细微差别?
【问题讨论】:
-
java 平台只有一种标准机制来中断线程。这是中断标志。并且线程应该自己检查标志。任何长/阻塞操作都应该检查这个标志。例如,如果你有一个长时间运行的循环,你应该定期检查 interrupted()/isInterrupted() 标志。顺便说一句,要中断像 socket.read() 这样的阻塞 IO 操作,更好的方法是在另一个线程中 close() 以立即从 read() 中退出并抛出 IOException。
-
2.不需要使用合成 volatile 标志来停止线程计算,但这可能是线程将被用户停止的标志,因此,将标志关闭设置为 true 并在运行的 catch 部分检查它( ) 方法。如果 !close,你有问题,否则这是从 run() 退出的预期异常。 3.不要忘记,通常建议在捕获InterruptedException后恢复中断标志javapractices.com/topic/TopicAction.do?Id=251
-
@AnatolyG 有时会调用 interrupt() 来唤醒正在休眠或等待可中断锁的线程,而不打算停止它。在这种情况下,检查 interrupted()/isInterrupted() 是不够的。中断的另一个问题是它们会在中间中断某些功能,而最好将文件读到最后,然后检查自定义标志。
-
@Andrea 当然,我可以想象这样的独家设计方案:),但在我看来,这似乎不是像 Object wait()/notify() 这样的规范的线程间通信机制,Locks+Conditions,BlockingQueues 等。我想在标准库或任何众所周知的库中看到一个例子。至于“中途中断某个函数”,这是合作机制(ibm.com/developerworks/library/j-jtp05236/index.html),也就是说如果这是你的函数,你可以在恢复中断标志并退出之前做你需要做的事情,例如,你关闭你的文件描述符。
-
但是如果 GUI 线程只是要求我们的解压缩函数停止,我希望该函数尽快停止并且不要读取和解压缩我的 10gigs 文件的其余部分)如果我们想使用ExecutorService 中的函数,该服务不知道我们自己的自定义标志,而只知道中断。
标签: java multithreading