2017-03-16 5 views
2

Companyクラスには、3つのスレッドで更新しようとしている5 ArrayListが含まれています。 addToWorkers()メソッドは、Employeeサブクラスの型を取得し、対応する配列に追加します。会社のシングルトンインスタンスは静的でなければならず、同期を提供する必要があるため、私はLazyHolderクラスを使用しています。すべてのリスト型の変数は、volatileであり、私が使用している方法があれば、私は私のメインを実行することを、私は期待したい​​あるので3つのスレッドを持つ5 ArrayListに要素を追加する:arraylistのサイズの合計は常に異なる

public class Runner implements Runnable { 

    private Random random = new Random(); 
    private Position[] positions = Position.values(); 

    final Position randomPosition(){ 
     return positions[random.nextInt(positions.length)]; 
    } 

    public void run() { 
     for (int i = 1; i <= 350; i++) { 
      Position p = randomPosition(); 
      switch (p) { 
       case PROJECT_LEADER: 
       Company.getInstance().addToWorkers(new ProjectLeader(p, "projectLeader")); 
        break; 
       case DEVELOPER_LEADER: 
       Company.getInstance().addToWorkers(new DeveloperLeader(p, "developerLeader")); 
        break; 
       case CONSULTANT_LEADER: 
        Company.getInstance().addToWorkers(new ConsultantLeader(p, "consultantLeader")); 
        break; 
       case DEVELOPER_WORKER: 
       Company.getInstance().addToWorkers(new DeveloperWorker(p, "developerWorker")); 
        break; 
       case CONSULTANT_WORKER: 
       Company.getInstance().addToWorkers(new ConsultantWorker(p, "consultantWorker")); 
        break; 
      } 
     } 
    } 
} 

public class Company { 

    private static class LazyHolder { 
     private static final Company INSTANCE = new Company(); 
} 

    private volatile List<ProjectLeader> projectLeaders = new ArrayList<>(); 
    private volatile List<ConsultantLeader> consultantLeaders = new ArrayList<>(); 
    private volatile List<DeveloperLeader> developerLeaders = new ArrayList<>(); 
    private volatile List<DeveloperWorker> developerWorkers = new ArrayList<>(); 
    private volatile List<ConsultantWorker> consultantWorkers = new ArrayList<>(); 

    private Company() { 
    } 

    public static Company getInstance() { 
     return LazyHolder.INSTANCE; 
    } 

    public synchronized <T extends Employee> void addToWorkers(T t) { 
     Position p = t.getPosition(); 
     switch (p) { 
      case DEVELOPER_WORKER: Company.getInstance().developerWorkers.add((DeveloperWorker) t); 
       break; 
      case DEVELOPER_LEADER: Company.getInstance().developerLeaders.add((DeveloperLeader) t); 
       break; 
      case CONSULTANT_WORKER: Company.getInstance().consultantWorkers.add((ConsultantWorker) t); 
       break; 
      case CONSULTANT_LEADER: Company.getInstance().consultantLeaders.add((ConsultantLeader) t); 
       break; 
      case PROJECT_LEADER: Company.getInstance().projectLeaders.add((ProjectLeader) t); 
       break; 
     } 
    } 
} 

RunnerクラスはRunnableインターフェイスを実装しますメソッドを使用して、各配列のサイズの合計を取得すると、毎回正確に1050になりますが、それはいつも1000-1100の間です。ArrayIndexOutOfBoundsException

t1.start(); 
    t2.start(); 
    t3.start(); 
    try { 
     t1.join(); 
     t2.join(); 
     t3.join(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    System.out.println(Company.getInstance().getConsultantLeaders().size() + 
      Company.getInstance().getDeveloperWorkers().size() + 
      Company.getInstance().getConsultantLeaders().size() + 
      Company.getInstance().getDeveloperLeaders().size() + 
      Company.getInstance().getProjectLeaders().size()); 

私はここで何が欠けていますか?

+0

'ArrayIndexOutOfBoundsException'はどこにスローされますか? –

+0

ランナークラス、void()メソッドが最後に追加されます。 – dmbdnr

+0

'Company'の' swith/case'にすべての 'Position'値を追加してもよろしいですか?警告があるかどうかを調べるために 'default'を追加することができます。 –

答えて

0

があなたのロジックによると、すべてのスレッドのためのあなたのリストが表示されるようにする理由はない、

public synchronized <T extends Employee> void addToWorkers(T t) 

は、それがスレッドセーフにするには十分であるが、この方法でマルチスレッドを使用することも意味がありません。

私はあなたがこのようなあなたのリストを定義することをお勧め:

private List<ProjectLeader> projectLeaders = Collections.synchronizedList(new ArrayList<>()); 
private List<ConsultantLeader> consultantLeaders = Collections.synchronizedList(new ArrayList<>()); 
private List<DeveloperLeader> developerLeaders = Collections.synchronizedList(new ArrayList<>()); 
private List<DeveloperWorker> developerWorkers = Collections.synchronizedList(new ArrayList<>()); 
private List<ConsultantWorker> consultantWorkers = Collections.synchronizedList(new ArrayList<>()); 

今、私たちはあなたの本当の問題を解決することができ、この1つは面白いです:)

あなたの合計を確認し、あなたがにconsultantworkersに追加されていません合計、あなたは二度のためのコンサルタントの指導者を追加する:

System.out.println(
     Company.getInstance().getConsultantLeaders().size() + // leaders 
     Company.getInstance().getDeveloperWorkers().size() + 
     Company.getInstance().getConsultantLeaders().size() +//this one must be workers 
     Company.getInstance().getDeveloperLeaders().size() + 
     Company.getInstance().getProjectLeaders().size()); 

あなたはまた、労働者を必要とする;)

+0

私はconsultantWorkersを2回追加したとは思えません。それは私を狂わせてしまいました、ありがとう! – dmbdnr

+0

@dmbdnrのリーダー* :) –

+0

ええ、その1つ!しかし、私はまだあなたがなぜaddToWorkersの引数型をIntegerに変更したのか分からない。あなたはそれを説明できますか? – dmbdnr

関連する問題