Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-Threading not working correctly

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: enter image description here

like image 940
137 Avatar asked Jul 13 '13 22:07

137


People also ask

Why multithreading is not working in Python?

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.

How will you avoid the discrepancy that can occur of multiple threads run simultaneously?

Thread interference errors can be avoided by synchronizing access to shared variables.


1 Answers

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.

  1. The run() method you gave is inside the Job class.
  2. The "cancel" button you refer to is the 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.

like image 162
Matt McHenry Avatar answered Oct 14 '22 08:10

Matt McHenry