Modifica Questo post riguarda un compito a casa che ho per la scuola che detta mi baso sullo swing per visualizzare i miei thread e le bandiere booleane per il blocco.Multi-Threading non funziona correttamente
La mia applicazione crea un gruppo di oggetti "lavoro" che contengono ciascuno un thread. Ogni lavoro appartiene a una creatura. Una creatura può avere più lavori ma può eseguirne solo 1 in un dato momento.
Il mio thread utilizza 2 flag booleani per indicare se è necessario eseguire "killFlag" e "goFlag". Indica la creatura a cui appartiene come "bersaglio". E ogni obiettivo ha un "bozza" booleana per indicare se è occupato o meno con un altro lavoro.
Questo è il filo ogni lavoro deve essere eseguito:
public void run() {
long time = System.currentTimeMillis();
long startTime = time;
long stopTime = time + 1000 * (long)(jobTime);
double duration = stopTime - time;
synchronized (this.target) {
while (this.target.isWorking) {
status = 'w';
showStatus(); // hmmmmmmmm
try {
this.target.wait();
} catch (InterruptedException e) {
}
}
this.target.isWorking = true;
}
while (time < stopTime && !killFlag) {
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
}
if (goFlag) {
status = 'p';
showStatus();
time += 100;
this.showProgress.setValue((int)(((time - startTime)/duration) * 100));
} else {
status = 'r';
showStatus();
}
}//End While loop here
showProgress.setValue(100);
status = 'c';
showStatus();
synchronized (target) {
target.isWorking = false;
target.notifyAll();
}
}
In un primo momento ho pensato che fosse target.notifyAll()
perché sta gettando un IllegalMonitorStateException
, ma quando io commento fuori il filo sarà oggetti costruirà ma quando osservo nella GUI l'80% di essi viene visualizzato come completo senza alcuna interazione da parte mia e l'altro 20% afferma che la creatura è occupata.
In un primo momento ho pensato che fosse perché ho inserito la bandiera di uccisione troppo presto ma quando l'ho spostato più in basso o rimosso, i sintomi persistono ancora. Sono schierato al momento e non ci sono programmatori qui haha, ogni consiglio che potresti fornire significherebbe il mondo.
Per garantire che fornisco informazioni sufficienti di seguito sono i metodi che utilizzo per interagire con i thread. I metodi seguenti funzionano con un pulsante che cambia in base al fatto che il thread sia in esecuzione o meno.
public void showStatus() { //switch that changes status of button used to start/pause/display status of thread
switch (this.status) {
case 'r' :
startJob.setEnabled(true);
startJob.setText ("Run");
break;
case 'p' :
startJob.setEnabled(true);
startJob.setText("Pause");
break;
case 'w' :
startJob.setEnabled(false);
startJob.setText("Working");
break;
case 'c' :
startJob.setEnabled(false);
startJob.setText("Job Complete");
break;
}
}
private class theHandler implements ActionListener {//Listener for Button mentioned above
public void actionPerformed (ActionEvent event) {
if (event.getSource() == startJob) {
if (goFlag) {
goFlag = false;
} else {
goFlag = true;
killFlag = false;
}
} else if (event.getSource() == stopJob) {
if (killFlag) {
//do nothing
} else {
killFlag = true;
status = 'r';
}
}
}
}
Questo mi sta uccidendo, ho scavato intorno per risolvere questo per 6 ore.
Modifica
Dopo aver regolato il mio codice in base a commento di MadProgrammer il "target.notifyAll()" è fissa. Ora sembra che tutti i thread appaiano sul display come completi anche se i pulsanti lampeggiano casualmente tra stati per una frazione di secondo.
Modifica
Un sacco di modifiche inseriti in risposta ai commenti
Di seguito è riportato come mi definisco la classe lavoro in cui sono definiti killFlag, goFlag, ecc.
class Job extends Item implements SearchableByName, Runnable {
int index;
String name;
int creature;
double jobTime;
Creature target;
boolean goFlag = false;
boolean killFlag = false;
char status;
JButton startJob;
JButton stopJob;
JProgressBar showProgress;
JPanel p1;
Di seguito è dove Creature (target) è definito in cui booleano isWorking risiede:
class Creature extends Entity implements SearchableByName, SearchableByType, Runnable {
int party;
int empathy;
int fear;
int carryCapacity;
Float age;
Float height;
Float weight;
boolean isWorking = false;
E in risposta ai commenti: ecco un quadro di come io sono la visualizzazione dei fili:
Il nuovo codice deve utilizzare le astrazioni di concorrenza di livello superiore. Dovresti definire il tuo progetto in termini di compiti ed esecutori, piuttosto che discussioni. È particolarmente difficile utilizzare wait, notify e notifyAll correttamente. Il modo in cui discuti il modo in cui desideri coordinare i tuoi thread, probabilmente dovresti usare CountDownLatch. I tuoi flag semaforo home dovrebbero essere dichiarati volatili, dato che non stai garantendo che gli aggiornamenti che creerai saranno visibili ad altri thread. – scottb
Mentre c'è un'indicazione della GUI, non c'è identificazione del framework. Se stai usando swing, ti consiglio vivamente di dare un'occhiata a [Concurrency in Swing] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) mentre stai violando le regole del singolo thread;) – MadProgrammer
target.notifyAll deve essere eseguito all'interno di un blocco sincronizzato, poiché notifyAll richiede il blocco del monitor per funzionare – MadProgrammer