2

私は、各スレッドがrandomly find columns for that tableそれらの列を使用するマルチスレッド プロジェクトに取り組んでおり、SELECT sql queryその SELECT SQL クエリを実行します。そのクエリを実行した後、結果セットをループして、各列のデータを に追加しますList<String>

ここには で区切られたものcolumnsListが含まれます。例えば-columnscomma

col1, col2, col3

以下は私のコードです。

class ReadTask implements Runnable {

public ReadTask() {

}


@Override
public run() {
  ...

  while ( < 60 minutes) {

    .....

    final int id = generateRandomId(random);
    final String columnsList = getColumns(table.getColumns());
    final String selectSql = "SELECT " + columnsList + "  from " + table.getTableName() + " where id = ?";
    resultSet = preparedStatement.executeQuery();

    List<String> colData = new ArrayList<String>(columnsList.split(",").length);
    boolean foundData = false;

    if (id >= startValidRange && id <= endValidRange) {

        if (resultSet.next()) {
            foundData = true;
            for (String column : columnsList.split(",")) {
                colData.add(resultSet.getString(column.trim()));
            }
            resultSet.next();//do I need this here?
        }
    } else if (resultSet.next()) {
        addException("Data Present for Non Valid ID's", Read.flagTerminate);
    }

    ....
      }
   }


    private static void addException(String cause, boolean flagTerminate) {
        AtomicInteger count = exceptionMap.get(cause);
        if (count == null) {
            count = new AtomicInteger();
            AtomicInteger curCount = exceptionMap.putIfAbsent(cause, count);
            if (curCount != null) {
                count = curCount;
            }
        }
        count.incrementAndGet();

        if(flagTerminate) {
            System.exit(1);
        }
    }
}

問題文:-

SELECTSQLクエリを実行した後。以下は私の2つのシナリオです-

  1. ID が有効な範囲内にあるかどうかを確認する必要があります。有効範囲内にある場合resultSetは、データがあるかどうかを確認します。データがある場合は、 fromresultSetを使用してループし、文字列のリストに追加し始めます。columnscolumnsListcoldData
  2. それ以外の場合、id が有効な範囲内にない場合は、からデータが返されていないことを確認する必要がありますresultSet。しかし、何らかの形でデータを取得していて、プログラムを停止するためにフラグが true の場合は、プログラムを終了します。それ以外の場合は、データを取得しているが、プログラムを停止するためにフラグが false の場合は、それらが何回発生しているかを数えます。このため、addExceptionメソッドを作成しました。

上記の2つについて私がここで行っている方法scenariosが正しいかどうか、誰かが私を助けてくれますか? if/else loop上記の 2 つのシナリオでは、コードをさらに改善できるようです。

4

1 に答える 1

2

コードを少し速くするためにできることは、おそらくいくつかあります。

クエリ部分に関しては、テーブルが変更されない場合は、columnsList初期化を while ループの外に移動し、すべてのスレッドが同じクエリを使用する場合は静的にすることもできます。同様に、クエリ結果ごとに、この変数から分割およびトリミングされた列のリストを再計算しています。これは、ループの外側で一度だけ実行できます。

テスト自体に関しては、確かにネストを逆にすることができました。あなたは現在次のようなことをしています:

if (B) {
   if (A) ok;
}
else if (A) error;

もっと簡単に書くことができるとき:

if (A){
   if (B) ok;
   else error;
}

コードは次のように記述できます。

if (resultSet.next()) {
    if (id >= startValidRange && id <= endValidRange) {
        foundData = true;
        for (String column : columnsList.split(",")) {
            colData.add(resultSet.getString(column.trim()));
        }
    }
    else
        addException("Data Present for Non Valid ID's", Read.flagTerminate);
} 

例外ログの部分に関しては、静的メソッドを使用してマップ内のストレージを直接処理することは避ける必要があります。これは、強力な競合の原因となり、スレッドが実際の作業 (クエリの起動と処理) に集中できなくなります。通常、 ではマップへのアクセスに時間がかかりO(log n)ます。コードを見ると、そのアクセスを 2 回行っており、アカウンティングが正しいことを確認するためにあらゆる種類のチェックを行っています。比較すると、キューに値をプッシュすることは一定時間の操作であり、同期はキュー自体によって処理されます。

したがって、ここでの私のアドバイスは、マップの処理を専用スレッドに委譲し、クエリ スレッドに同期キューを追加して例外を与えることです。そうすれば、マップへの同時アクセスを処理する必要がなくなります (これは面倒です)。繰り返しますが、クエリ スレッドの観点から見ると、ロギング プロセスは単純な「起動して忘れる」アクションになり、ロギング スレッドはキューから新しいメッセージを取得してマップに追加するだけで済みます。

このようなセットアップを構築する方法がまだわからない場合は、Oracle のチュートリアルがあります。トピック(生産者 - 消費者)に関するいくつかのSOの質問と回答もあります。

更新: 競合を減らしたい場合は、クエリ スレッドごとに 1 つのキューを作成し、マップ スレッドにすべてのキューを順番にチェックさせることができます。同時アクセスのリスクは、同時に 2 つのスレッド (1 つのクエリ スレッドとマップ スレッド) に減少します。これにより、マップ スレッドでの作業が少し増えますが、同時に、多くのスレッドの再スケジュール (スレッドがロックによってブロックされるたびに発生します) を回避できます。再スケジュールが少ないほど、スレッド管理に費やされる時間が減り、実際の作業により多くの時間を割くことができます。

いずれにしても、あまりにも多くのアイテムがキューに積み上げられないように注意する必要があります。そのシナリオが発生する可能性が高い場合 (疑いますが、データの詳細が確実かどうかはわかりません)、BlockingQueues を使用することをお勧めします (クラスの説明を調べ、詳細についてはトピックに関する SO の質問を参照してください)。 )。

于 2013-03-01T03:17:03.437 に答える