2016-05-11 15 views
0

ラウンドロビンとして動作するメソッドを記述しました。誰かがそれを呼び出すたびに、リストから整数を返します。リストの終わりに達すると、それは最初から提供を開始します。マルチスレッド環境でのリストのラウンドロビン

私はこのメソッドをステートレスセッションBeanから呼び出します。

私は私が書いたことは権利であると動作しますどこまでわからない

public final class MyUtil { 

    private static int index; 

    private MyUtil() {} 

    public synchronized static int getNextInt() { 
     Properties p = DBconfigModule.getProperties("key"); 
     List<String> list = Arrays.asList(((String) p.get("key")).split(",")); 
     try { 
     if(index>=list.size()) { 
      index = 0; 
      next = list.get(0); 
      index++; 
     } else { 
      next = list.get(index): 
      index++; 
     } 
     } catch(final Exception e) { 
      // log 
      index = 0; 
      next = list.get(0); 
      index++; 
     } 
    return Integer.parseInt(next); 
} 

@Stateless 
public class Usage { 
    public int getNextInt() { 
     return MyUtil.getNextInt(); 
    } 
} 

以下のような方法がutilのクラスで書かれています。

誰も私にこの権利があると教えてもらえますか?改善できるかどうか教えてください。

私はこれに3ppライブラリを使用したくありません。

ありがとうございます。

+0

問題がありますか?コードレビューを求める場合は、http://codereview.stackexchange.com/ – Qwerky

+0

を参照してください。レビューを依頼しています。ありがとう、私はそこにそれを投稿します –

+0

Re、 "私が書いたこと[...]はうまくいくかはわかりません。"だからそれを試して、そう? –

答えて

1

あなたのコードは、listが変更されていない場合、またはリストへのアクセスが同じモニターで​​の場合にのみ正しいです。以下のコードが実行されたときに何が起こるか想像し

:非常に大まかにそのような

Thread 1       Thread 2 
-------------------    ----------------------- 
// index = 2 
// list.size() = 3 
if (index == list.size()) { 

            // Removes first element 
            // now list.size() = 2 
            list.remove(0); 


} else { 
    // Will throw an exception 
    // Because now list has size 2 
    // and the third element (index 2) 
    // doesn't exists 
    next = list.get(index); 
+0

はい、あなたは正しいです。バグを指摘してくれてありがとう。あなたが言及したように、リストは時々変更されるでしょう。 'if(index> list.size())、index = 0'のようなサイズのチェックを追加すると、この問題を解決できますか? –

+1

リストを変更するコードを、同じモニターを使用して同期ブロックで囲むことはできます。 –

+0

いいえリストが別の場所で変更されているため不可能です。データベーステーブルの変更をリッスンするキャッシュからリストをロードします。テーブルに変更があると、キャッシュがリフレッシュされます。それが理由で、私はキャッシュから常にリストをロードしています –

0
import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.atomic.AtomicInteger; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReadWriteLock; 
import java.util.concurrent.locks.ReentrantReadWriteLock; 


public class Counter { 

    private ReadWriteLock listLock = new ReentrantReadWriteLock(); 

    private List<Integer> list = new ArrayList<>(); 

    private AtomicInteger indexCounter = new AtomicInteger(0); 

    Integer getNextInt() { 
     Lock readLock = listLock.readLock(); 
     try { 
      if(list==null || list.size() == 0) { 
       throw new IllegalStateException("Call setList() with some values first."); 
      } 
      int index = indexCounter.incrementAndGet() % list.size(); 
      return list.get(index); 
     } finally { 
      readLock.unlock(); 
     } 
    } 

    void setList(List<Integer> newList) { 
     Lock writeLock = listLock.writeLock(); 
     try { 
      this.list = newList; 
     } finally { 
      writeLock.unlock(); 
     } 
    } 
} 

何か、。

+0

バグを指摘してくれてありがとう。リストに値を設定するコードは、従来のコードです。私はそれを変更できるとは思わない。私のコードでtry catchを追加しました。私は、レガシーコードにロックを加えるオリジナルの開発者に影響を与えようとします。ありがとうございました。 –

関連する問題