user2209743 user2209743 - 9 days ago 6
Java Question

Removing a println call in java is causing a logical error

I've been working on a program for a few weeks now and someone gave me a suggestion on how to improve it's performance which I am attempting to implement. It is so far working however, I have run into the issue that I cannot comment out one of the println calls I had previously added to help debug and still get the desired output. the code in question is

if (distTable != null)
{
//System.out.println("test");
float [] distLine;
for (int i = 0; i < s.emitters.length; i++)
{
int tx = s.emitters[i].getX();
int ty = s.emitters[i].getY();
for (int x = 0; x < matrix.length; x++)
{
distLine = distTable[Math.abs(x-tx)];
for (int y = 0; y < matrix[x].length; y++)
{
matrix[x][y] += s.emitters[i].amplitudeAtDist(distLine[Math.abs((y * targetThreads)+threadNumber - ty)]);
}
}
System.out.println("test " + i + " " + threadNumber);
}
callback.alertComplete(this);
return;
}


the above code works as expected however, the code below does not and instead the program produces no output at all. The only difference is that the code below has one println call commented out.

if (distTable != null)
{
//System.out.println("test");
float [] distLine;
for (int i = 0; i < s.emitters.length; i++)
{
int tx = s.emitters[i].getX();
int ty = s.emitters[i].getY();
for (int x = 0; x < matrix.length; x++)
{
distLine = distTable[Math.abs(x-tx)];
for (int y = 0; y < matrix[x].length; y++)
{
matrix[x][y] += s.emitters[i].amplitudeAtDist(distLine[Math.abs((y * targetThreads)+threadNumber - ty)]);
}
}
//System.out.println("test " + i + " " + threadNumber);
}
callback.alertComplete(this);
return;
}


the above code is a part of the run method in a Runnable class and it is being executed as a separate thread from the main program.

the code in the alertComplete method called at the end is:

public void alertComplete(SimThread s) {
completedThreads ++;
int threadNumber = s.getThreadNumber();
int targetThreads = s.getTargetThreads();
double[][] temp = s.getResultMatrix();
for (int x = 0; x < temp.length; x++)
{
for (int y = 0; y < temp[x].length && (y*targetThreads)+threadNumber < tempMatrix[x].length; y++)
{
double t = temp[x][y];
tempMatrix[x][(y*targetThreads)+threadNumber] = t;
}
}
if (completedThreads == MAXTHREADS)
{
System.out.println("Calculating points took " + ((System.currentTimeMillis() - startTime)) + " milliseconds.");
normalizeAndDraw(tempMatrix);
}

}


the println call in this method does not execute when the println in the above code is commented.

Answer

It is very hard to analyze the problem without being able to run it.

My guess would be to synchronize alertComplete, or better, synchronize the access to completedThreads - eventually the problem is that two or more Threads are updating the counter at the same time so it never reaches MAXTHREADS. Or try using an AtomicInteger for the counter...

But this is just a very rough guess since I haven't got the whole idea...

Assuming that the counter is only used in alertComplete, you could do :

private final Object counterLock = new Object(); // could use any other existing (meaningfull) object

...

public void alertComplete(SimThread s) {
    bollean done;
    synchronized (counterLock) {
        completedThreads ++;
        done = completedThreads == MAXTHREADS;
    }

    ...

    if (done)
    {
        System.out.println("Calculating points took " + ((System.currentTimeMillis() - startTime)) + " milliseconds.");
        normalizeAndDraw(tempMatrix);
    }

}

or just declare the method synchronized (for testing):

public synchronized void alertComplete(SimThread s) {
    ...
}
Comments