0

状況は、getConnection を試行したときに RecoveryThread が 1 つだけ作成されるようにする必要があり、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 を試行する 2 つの異なるスレッドがある場合、これにより requestFailover() メソッドが 2 回呼び出される可能性があり、2 回呼び出されると、2 つの recoveryService スレッドが作成されることになります。

よろしくお願いします。

4

2 に答える 2

5

決して起こらないようにするにはどうすればよいですか?

Executors.newSingleThreadExecutor()考慮すべきことの 1 つは、実行を行うために 1 つのスレッドのみをフォークする の使用に切り替えることです。その後、タスクが重複することを心配することなく、必要な数のタスクを送信できます。

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 メソッドに「synchronized」修飾子を追加し、ブール値フラグを追加して、フェイルオーバーがすでに要求されているかどうかを示すことができます。

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

これにより、2 つのスレッドが同時に getConnection() メソッドに入るのを防ぎ、スレッドがフェイルオーバーを要求した場合に、別のスレッドが getConnection() に入るのを許可する前に、そのスレッドが alreadyRequestedFailover フラグを更新するようにします。

于 2013-11-05T18:05:50.437 に答える