2012-02-17 13 views
0

私はベクトルを含むシングルトンロガーを持っています。外部からのオブジェクトは、singletonLogger.append(String data)を呼び出してこのベクトルに情報を追加し、文字列を返すsingletonLogger.getLogEntries()を呼び出してベクトル全体を読み取ることができます。 getLogEntriesメソッドをint型パラメータでオーバーロードするとよいでしょう。 getLogEntries(int x)、ログ全体ではなく最後のxエントリのみを取得できるようにします。スレッドセーフな状態でベクトルの最後のXエントリを読み取る方法は?

mutlipleスレッドに関するなければ、これは、のようなものは簡単だろう:

String getLogEntries(int x) { 

int size = vector.size(); 

for(int i = size; i > (size - x); i--) { 

    // StringBuilder.append(vector.elementAt.... 

} 
} 

しかし、アカウントに複数のスレッドを取ったときに、もちろん、これは本当に安全ではありません。上記の方法でサイズが決定された直後に別の方法でベクターがクリアされたとすると、ループはクラッシュします。

一方、ループ処理が5〜10秒続く可能性があるため、私はこのメソッド全体を同期としてマークしたくありません。これは、ロガーのメソッドを呼び出そうとしているすべてのコードをブロックするでしょうか?

ベクトルの最後のx要素を確実に得る別の方法はありますか?

おかげ

+0

ベクターを同期させるだけですか? – Jivings

+0

Uh。 'Vector'クラスはすでに定義されています。 – Gray

答えて

2

編集

ベクトルは動作するはずと同期させることがsublist methodているが、それは、誰かが別のスレッドでVectorをクリアし解決していません。 Vectorの最後からsublist()writeLock()(排他的アクセスが保証されています)の末尾からclear()を呼び出す必要がある場合はReadWriteLockを使用し、readLock()を使用できます。あなたのバックグラウンドスレッドがディスクや何かにログエントリを書き込んでいる場合、書き込まれた行の数を数え、writeLock()を取得し、clear()の代わりにリストの先頭から削除してください。これは、ロックの下の時間をより効率的に制限します。

独自の内部キューを維持して、特に同期を制御できるようにすることも考えられます。これにより、以前のエントリをキューから簡単にクリアすることができます。その後、もう一度ReadWriteLockが必要になることがあります。

+0

皆様おかげさまで私はベクトルがすでにスレッドセーフであることを知っていましたが、これは私の問題を解決しないと思います。想像してみてください。 'subList(vector.size() - x、vector.size())'。 subListが実行されてもこれらのインデックスが有効であるとは限りません。 – ceran

+0

これは、両方のインデックスが一貫していることを保証します。しかし、別の時刻に決定されてからサブリスト・メソッドが実行されるため、ベクトルにまだそれらのインディケータが含まれていることは保証されません。 **編集:** hm、あなたのコメントは消えました:D – ceran

+1

基礎となるベクトルを変更した後にこのメソッドから返されたリストを使用すると、同時変更例外が発生します。これは、マルチスレッドアプリケーションにとっては非常に不適切です。 – Perception

1

​​ブロック内の新しいVectorに関連する要素をコピーし、それらを外部で処理することを検討しましたか?

関連する問題