Company
类包含5个ArrayList,我正在尝试用3个线程更新。 addToWorkers()
方法获取Employee
子类的类型,并将它们添加到相应的数组中。我正在使用LazyHolder类,因为我的公司单例实例必须是静态的,它应该提供同步。
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
接口:
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;
}
}
}
}
由于所有List类型变量都是volatile
而我正在使用的方法是synchronized
我希望,如果我运行我的main方法,并得到每个大小的总和数组,我每次都会得到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 :(得分: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<>());
现在我们可以解决你的真正问题,这个很有趣:)
检查您的金额,您不是要向顾问工作者添加金额,您要两次添加顾问领导者:
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());
你还需要工人;)