情况是,当我尝试 getConnection 时,我必须确保只创建一个 RecoveryThread,如果 PrimaryData Source 上的 getConnection 失败,则我的代码是:
public Connection getConnection() throws SQLException {
if (isFailedOver()) {
try {
return failoverDataSource.getConnection();
} catch (SQLException e) {
throwBigError();
}
}
Connection connection = null;
try {
connection = dataSource.getConnection();
return connection;
}
catch (SQLException unexpected) {
return requestFailover();
}
}
private Connection requestFailover() throws SQLException {
this.dbFailoverMutex.requestFailover();
DBFailoverRecoveryService recoveryService = new DBFailoverRecoveryService(this.dbFailoverMutex,this.dataSource);
Thread recoveryServiceThread = new Thread(recoveryService, "DBFailover Recovery Service");
recoveryServiceThread.start();
try {
return failoverDataSource.getConnection();
} catch (SQLException e) {
throwBigError();
}
return null;
}
如果有两个不同的线程尝试 getConnection,这可能最终会调用 requestFailover() 方法两次,并且当它被调用两次时,这将最终创建两个 recoveryService 线程,我该怎么做才能确保永远不会发生这种情况?
预先感谢您的帮助。
最佳答案
what can I do to make sure that never happens?
需要考虑的一件事是改用 Executors.newSingleThreadExecutor()
这只会 fork 一个线程来执行运行。然后您可以提交任意数量的任务,而不必担心它们重叠。
private final ExecutorService threadPool =
Executors.newSingleThreadExecutor(/* pass in ThreadFactory to set name */);
...
DBFailoverRecoveryService recoveryService =
new DBFailoverRecoveryService(this.dbFailoverMutex, this.dataSource);
threadPool.submit(recoveryService);
一如既往地使用 ExecutorService
,您需要调用threadPool.shutdown()
一旦您将最后一个任务提交到池中,否则它将挂起您的应用程序。您可以添加 Datasource.destroy();
方法来做到这一点。
关于java - 如何确保只有一个线程启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19795652/