マルチスレッド環境での割り当てリストを維持する必要があります。 Executorサービスはサーバースレッドを数分間実行し、 各スレッドは共有リストから割り当てを追加または削除できます。共有リストでのマルチスレッドの処理
2つ以上のスレッドが同じ割り当てを削除しようとしている状況を防ぐ必要があります。
私は、どのコレクションを使用するか、どのように使用するかを決定するためにtrubleを持っています。 同期化されたブロックの中にリストをラップすることなくそれを行う方法はありますか?
私が読んだところから、CopyOnWritearraylistは主に読み込みに適しています。 Collections.synchronizedListは答えですか?
ありがとうございました。
public class AssignmentsListComponent {
private List<Assignment> assignmentsList;
private boolean isClosed;
public AssignmentsListComponent(List<Assignment> assignmentsList) {
super();
this.assignmentsList = assignmentsList;
this.isClosed = false;
}
public void addAssignment(Assignment assignment) throws ClosedAssignmentsListException{
if(this.isClosed)
throw new ClosedAssignmentsListException("Cannot add Assignment. List is closed");
this.assignmentsList.add(assignment);
}
public void removeAssignment()throws ClosedAssignmentsListException{
if(this.isClosed)
throw new ClosedAssignmentsListException("Cannot add Assignment. List is closed");
Assignment assignmentToRemove = this.assignmentsList.get(new Random().nextInt(this.assignmentsList.size()-1));
this.assignmentsList.remove(assignmentToRemove);
this.isClosed = this.assignmentsList.isEmpty();
}
}
public class SchedulerService {
private final static long PERIOD = 1500;//Repeat interval
private final static long TIME_TO_RUN = 5;
private Map <Family, AssignmentsListComponent> familyAssignmentsListMap;
private void initializeFamilyAssignmentsListMap(){
List<Family> families = HibernateUtil.getAllFamilies();
for(Family family :families){
List<Assignment> assignmentsList = new ArrayList<Assignment>();
AssignmentsListComponent assignmentsListComponent = new AssignmentsListComponent(assignmentsList);
this.familyAssignmentsListMap.put(family, assignmentsListComponent);
}
}
public void runFamilyMemberThreds(){
List<Assignment> allAssignments = HibernateUtil.getAllAssignments();
List<FamilyMember> familyMembers = HibernateUtil.getAllFamilyMembers();
// create executor to run the threads for all family members
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(familyMembers.size());
/**
* For each of the family members, run in PERIOD intervals, and kill it's task after TIME_TO_RUN in minutes
*/
for(FamilyMember familyMember :familyMembers){
// Execute task every 30 seconds
final ScheduledFuture<?> handler = executorService.scheduleAtFixedRate(new FamilyMemberThred(familyMember, allAssignments, familyAssignmentsListMap.get(familyMember.getFamily())),0,PERIOD,TimeUnit.MILLISECONDS);
Runnable cancel = new Runnable()
{
public void run()
{
handler.cancel(true);
}
};
executorService.schedule(cancel,TIME_TO_RUN,TimeUnit.MINUTES);//Cancels the task after 5 minutes
executorService.shutdown();
}
}
}
public class FamilyMemberThred implements Runnable{
private List<Assignment> allAssignments;
private FamilyMember familyMember;
private AssignmentsListComponent assignmentsListComponent;
public void run() {
if(isAddAssignment())
addAssignment();
else
removeAssignment();
}
private void addAssignment(){
Assignment randomAssignmentToAdd = this.allAssignments.get(new Random().nextInt(allAssignments.size()-1));
try {
this.assignmentsListComponent.addAssignment(randomAssignmentToAdd);
} catch (Exception e) {
logClosedListException(randomAssignmentToAdd);
}
}
private void removeAssignment(){
try {
this.assignmentsListComponent.removeAssignment();
} catch (Exception e) {
logClosedListException(null);
}
}
private void logClosedListException(Assignment assignment){
Log log = new Log(familyMember, Action.ADD, assignment, Boolean.FALSE);
HibernateUtil.saveLog(log);
}
/**
* possible values between 0-2, so if 1 or 2, return true
*/
private boolean isAddAssignment(){
return new Random().nextInt(3) > 0;
}
}
実際にはget(index)のようなListメソッドが必要ですか?そうでない場合、これはBlockingQueueの完璧なユースケースのように思えます。 – yshavit
私はしませんが、なぜ私は割り当ての数に制限がなく、リストがクリアされたら、私はそれを閉じ、次の追加を待つことはないので、完璧なユースケースです。 – user3845295
呼び出し 'put'に値を入れているスレッド、それらを取り出すスレッドは' take'を呼び出し、同期は実装によって処理されます。 (put/take以外の方法がありますが、セマンティクスが異なります。https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.htmlを参照してください) – yshavit