0

情况是,我必须确保在尝试 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;
    }

如果有两个不同的线程试图获取连接,这可能会最终调用 requestFailover() 方法两次,当它被调用两次时,这将最终创建两个 recoveryService 线程,我能做些什么来确保永远不会发生?

在此先感谢您的帮助。

4

2 回答 2

5

我能做些什么来确保这种情况永远不会发生?

需要考虑的一件事是切换到使用一个Executors.newSingleThreadExecutor()只会派生一个线程来运行的线程。然后,您可以提交任意数量的任务,而不必担心它们重叠。

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();方法来执行此操作。

于 2013-11-05T18:03:18.577 回答
0

您可以将“同步”修饰符添加到您的 getConnection 方法,然后添加一个布尔标志以指示是否已请求故障转移,例如

public synchronized getConnection(){ throws SQLException
  if(alreadyRequestedFailover){
    return;
  }
  ....
  catch (SQLException unexpected) {
     alreadyRequestedFailover = true;
     return requestFailover();
  }
}

这将防止两个线程同时进入 getConnection() 方法,并确保如果一个线程请求故障转移,它将在允许另一个线程进入 getConnection() 之前更新 alreadyRequestedFailover 标志。

于 2013-11-05T18:05:50.437 回答