— Der Interesse halber —
In meiner Multithreadingumgebung gab es immer das Problem, das ein Thread Daten wollte zu denen der andere Thread noch garnicht gekommen war um sie zu bearbeiten und das ganze hat dann in einer Null-Pointer Exception geendet.
Das war vor allem das Problem beim instanziieren neuer Objekte. Jedes meiner Objekte legt auf jedem Thread eine neues Objekt von sich selbst ab um das typische Shared-Memory Problem zu umgehen.
Blöd nur wenn die Zwillingsobjekte versuchen auf sich gegenseitig zuzugreifen warten aber noch auf instanziierung.
—Das eigentliche Problem —
Also habe ich asynchrone Tasks eingeführt die dafür sorgen das alle Ressourcen geladen werden und bei Abschluss das eigentliche Objekt mit den geladenen Ressourcen aktivieren und dem System bekannt machen.
Das Problem ist jedoch, das der Profiler keine guten Ergebnisse dafür herausgibt.
So sieht die Klasse aus:
protected AbstractObject ao;
private volatile boolean hasLogicFinished = false, hasLookFinished = false;
private CoreManager database;
public AsynchronFactory(AbstractObject ao) {
this.ao = ao;
}
void setDatabase(CoreManager database) {
this.database = database;
}
@Thread#1
void initialize(Logic logic) {
init(logic);
hasLogicFinished = true;
checkIfFinished();
}
@Thread#2
private abstract void init(Logic logic);
@Thread#2
void initialize(Look look) {
init(look);
hasLookFinished = true;
checkIfFinished();
}
@Thread#2
private abstract void init(Look look);
@Thread#1
@Thread#2
private synchronized void checkIfFinished() {
if (hasLogicFinished && hasLookFinished) {
database.addObject(ao);
}
}
public AbstractObject getAbstractObject() {
return ao;
}
}
Meckern tut er in Zeile 31-35. Hier kommt es immer wieder zu Performancespitzen.
Meine Einschätzung ist, dass das synchronized das Problem ist weshalb der andere Thread warten muss.
Die Frage wäre ob ich das synchronized und eventuell sogar das volatile entfernen könnte ohne das er in der “checkIfFinished()”-Methode die Fallunterscheidung fälschlicherweise abbricht.
Sie muss einmal(!), und zwar wenn der letzte Thread die Methode aufruft, true sein und nur dann.
Vielleicht wäre ein Zähler eine bessere Idee? Aber Thread-eigene boolean Variablen erschienen mir sinnvoller als eine gemeinsame Zählvariable.
Ich glaube (bin mir aber nicht sicher) ich könnte synchronized rauslassen und es würde trotzdem funktionieren.
Man kann es halt nicht mal ausprobieren denn Multithreadingfehler passieren halt nur in “günstigen” Umständen und hier zählt das erfahrene Auge.
Der AsynchronTask wird nur einmal bisher ausgeführt und stirbt dann (vielleicht mache ich einen Pool daraus).