我已经在一个程序上工作了几个星期,有人给了我一个关于如何提高我正在尝试实现的性能的建议。然而到目前为止,它正在工作,我遇到了一个问题,我无法注释掉我之前添加的用于帮助调试的 println 调用之一,但仍然获得所需的输出。有问题的代码是
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;
}
上面的代码按预期工作,但是下面的代码却没有,并且程序根本不产生任何输出。唯一的区别是下面的代码注释掉了一个 println 调用。
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;
}
上面的代码是 Runnable 类中 run 方法的一部分,它作为与主程序分开的线程执行。
最后调用的alertComplete方法中的代码为:
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);
}
}
当上述代码中的 println 被注释时,该方法中的 println 调用不会执行。
最佳答案
如果不能运行问题,就很难分析问题。
我的猜测是同步alertComplete
,或者更好,同步对completedThreads
的访问 - 最终问题是两个或更多线程同时更新计数器时间,因此它永远不会达到 MAXTHREADS
。或者尝试使用 AtomicInteger
作为计数器...
但这只是一个非常粗略的猜测,因为我还没有完整的想法......
假设计数器仅在alertComplete
中使用,您可以这样做:
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);
}
}
或者只是声明方法同步(用于测试):
public synchronized void alertComplete(SimThread s) {
...
}
关于java - 删除 java 中的 println 调用会导致逻辑错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40759043/