Edit This post pertains to a homework assignment I have for school that dictates I rely on swing to display my threads and boolean flags for blocking.
My application creates a bunch of "job" objects that each contain a thread. Each job belongs to a creature. A creature can possess multiple jobs but can only perform 1 of them at any given moment.
My thread utilizes 2 boolean flags to tell whether or not it should be running called "killFlag" and "goFlag". It designates the creature it belongs to as "target". And each target has a boolean "isWorking" to denote whether or not it is busy with another job.
This is the thread each job should run:
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();
}
}
At first I thought it was target.notifyAll()
because it is throwing an IllegalMonitorStateException
, but when I comment it out the thread will objects will construct but when I view them in the GUI 80% of them are displayed as complete without any interation from me and the other 20% are stating that the creature is busy.
At first I thought this was because I pop the kill flag too early but when I moved it lower or removed it the symptoms still persist. I'm deployed at the moment and there are no programmers here haha, any advice you could provide would mean the world.
For the sake of making sure I provide enough information below are the methods I use for interacting with the threads. The below methods work with a button that changes based on whether or not the thread is running.
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';
}
}
}
}
This is killing me, I've been digging around to solve this for 6 hours.
Edit
After adjusting my code based on MadProgrammer's comment the "target.notifyAll()" is fixed. Now the issue seems to be that all threads appear on the display as complete even though the buttons flash randomly between states for a fraction of a second.
Edit
A lot of edits included below in response to comments
Below is how I define the job class where killFlag, goFlag, etc. are defined.
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;
Below is where Creature (target) is defined where boolean isWorking resides:
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;
And in response to the comments here is a picture of how I am displaying the threads:
Python doesn't support multi-threading because Python on the Cpython interpreter does not support true multi-core execution via multithreading. However, Python does have a threading library. The GIL does not prevent threading.
Thread interference errors can be avoided by synchronizing access to shared variables.
Since some code is still missing, I'm going to enumerate some assumptions first; if any don't hold, my answer below may be incorrect.
run()
method you gave is inside the Job
class.stopJob
JButton
If you're intending to reuse the same Job
instance for the restart after the 1st run-through, then your basic problem is that your run()
method terminates. You have a while
loop that checks for !killFlag
, but once that loop ends (i.e. once the job is canceled and killFlag == true
), there is nothing that would cause it to go back to the beginning and await a subsequent goFlag == true
state to start running again. (Also, consider whether the stopJob
clause in your actionPerformed()
method needs to do something with goFlag
.)
On the other hand, if you're intending to create a new Job
instance to represent the restarted job, then you haven't shown any code that would do that.
I'm being a bit vague in my diagnosis above on purpose, to try to help you figure things out on your own -- that's the best way to learn. :) If you need more details, I can try to provide them, just LMK in a comment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With