Java 安全止动螺纹
我有一些课:Java 安全止动螺纹,java,multithreading,Java,Multithreading,我有一些课: @Component public MyClass { private volatile boolean stopped = false; public void verification() throws Exception { Thread kpiAllThread = getKPIAllThread(); try { for (int i = 0; i < poolSize; i++) {
@Component
public MyClass {
private volatile boolean stopped = false;
public void verification() throws Exception {
Thread kpiAllThread = getKPIAllThread();
try {
for (int i = 0; i < poolSize; i++) {
execDispatcher.put(processExecutor.submit(getCheckValuesInKPIConsumerTask(workingQueue)));
}
kpiAllThread.start();
} finally {
waitFinished();
}
}
public void setStop(bolean stopped) {
this.stopped = stopped;
}
private Thread getKPIAllThread() {
return new Thread(() -> {
try {
LOG.debug("KPIAllThread started!");
dao.getKpiAll(workingQueue);
for (int i = 0; i < poolSize; i++) {
workingQueue.put(() -> true);
}
} catch (Exception ex) {
LOG.error("KPIAllThread exception: ", ex);
} finally {
LOG.error("KPIAllThread finished!");
}
});
}
}
还有一个变量
stopped
,可以从外部设置为true
。如何在执行此操作时安全停止线程?因此,所有与数据库的连接都将关闭,线程将成功完成?停止线程的最干净、最安全的规则是,线程中运行的代码应定期检查一个条件(例如,boolean shouldExit()
)。当代码检测到该条件为真时,它应该停止正在执行的操作并终止
在线程中运行的代码应该经常检查这种情况,以便它能够合理快速地做出反应。根据经验,设置此条件后,线程应在不到一秒钟内退出。该检查通常类似于迭代池大小的for循环中的if(shouldExit())break。但是,dao.getKpiAll(workingQueue)
看起来可能很长,因此您可能会在getKpiAll
中进行更多检查
当您执行此检查时,必须确保每次条件变为true时代码都会干净地退出。例如,您可以使用finally
块来关闭任何连接等。如果在getKpiAll
期间发生这种情况,那么继续使用For
循环来处理项目等都没有意义
有时,这可能会变得更加棘手-例如,当线程正在等待网络操作时,您可能需要关闭网络套接字或类似的东西来中断它。在任何情况下,都要避免使用Thread.stop()
或Thread.interrupt()
——请参阅文档说明它们有问题的原因
如果您这样做,您可以随时从线程外部设置条件以请求线程终止。您可以创建类似于void requestExit()
的代码,并在那里设置一个布尔变量。调用requestExit()
后,调用Thread.join()
,并在适当的超时时间内等待线程执行其业务,检查条件并退出。同样,根据经验,超时时间是线程最长反应时间的3-10倍
看起来您已经为此目的设置了
setStopped(boolean stopped)
,但您没有检查它。首先,我将删除参数stopped
,因为将false
传递给它没有意义。其次,您需要如上所述添加检查。您可能希望使此变量对dao
可见-请记住,将其作为同步布尔方法公开比作为布尔字段公开要好得多。您需要停止以使线程可见,因此建议为线程创建一个类,并使其从runnable继承。然后你可以把包含stopped标志的对象传递给它。@NathanHughes,如果变量stopped
是从我的类之外设置的,我如何中断我的线程?比如plz。如果使用try with resources
和thread
被中断,所有连接和结果集都将关闭?是的,如果在try with resources
中打开连接,它应该自动关闭。在这种情况下,编译器实际上会为您添加finally
块,并在其中调用close()
。如果需要细粒度控制,请编写一个显式的try finally
,而不是try with resources
。
public void getKpiAll(final BlockingQueue<KeyPropertyIndex> kpiData) throws Exception {
LOG.debug("Starting getKpiAll");
try (final Connection con = dataSource.getConnection();
final Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) {
stmt.setFetchSize(Integer.MIN_VALUE);
try (final ResultSet rs = stmt.executeQuery(sqlGetAllkpi)) {
while (rs.next()) {
kpiData.put(new KeyPropertyIndexData(rs.getLong(1), rs.getString(2)));
}
}
LOG.debug("Finished get getKpiAll");
} catch (Exception ex) {
throw ex;
}
}