我正在编写一个应用程序来计算二次方程的delta和根,接受其系数作为输入。后来,我想给它一个GUI。
这是计算所有内容的类:
package functions;
import java.util.*;
public class Calculate implements Runnable {
double a=0;
double b=0;
double c=0;
double delta = 0;
double r1=0;
double r2=0;
Vector data=new Vector ();
public Calculate (Vector v) {
synchronized (data) {
synchronized (v) {
data = v;
}
a =(double) data.elementAt(0);
b =(double) data.elementAt(1);
c =(double) data.elementAt(2);
}
}
public double calcDelta () {
delta = b*b-4*a*c;
return delta;
}
public double root1 () {
r1 = (-b+Math.sqrt(delta))/(2*a);
return r1;
}
public double root2 () {
r2 = (-b-Math.sqrt(delta))/(2*a);
return r2;
}
public void createData (Vector z) {
synchronized (z) {
while (z.size()!=0) {
z.removeElementAt(0);
}
z.add(delta);
z.add(r1);
z.add(r2);
}
}
public void run () {
calcDelta();
root1 ();
root2 ();
//try {
createData (data);
//} catch (InterruptedException e) {}
}
}
我测试过并且运行良好。问题出在我为它写的测试代码中:
import java.util.*;
import functions.*;
public class Test {
double a=0;
double b=0;
double c=0;
Vector v = new Vector ();
public Test (double arturo, double bartolomeo, double cirinci) {
a=arturo;
b=bartolomeo;
c=cirinci;
synchronized (v) {
v.add(a);
v.add(b);
v.add(c);
}
}
public Vector makevector () {
return v;
}
public static void main (String [] args) {
double art = (double) Integer.parseInt (args[0]);
double bar = (double) Integer.parseInt (args[1]);
double car = (double) Integer.parseInt (args[2]);
Test t = new Test (art, bar, car);
Thread launch;
Vector data = t.makevector();
Calculate res = new Calculate (data);
launch = new Thread (res);
launch.start();
if (data.size()!=0) {
System.out.println ("Delta: "+data.elementAt(0));
System.out.println ("Radice 1: "+data.elementAt(1));
System.out.println ("Radice 2: "+data.elementAt(2));
}
}
}
,特别是在Delta的输出中。事实上,根被正确显示,但是它不是delta,而是打印a系数(例如,如果我通过1 1 -6,我希望delta为25,但它显示1;如果是s 2 2 -12 delta仍然是25岁,但它显示2)。 不知何故,这个载体的第一个元素没有被删除和替换,但我不知道为什么;我只知道它不是同步问题,因为我试图删除所有的同步,输出是相同的。
那么,我的错误是什么?谢谢。
答案 0 :(得分:0)
synchronized (data) {
这会同步您以后永远不会使用的对象
launch.start();
if (data.size()!=0) {
在使用数据之前,您甚至不等待线程完成,尝试添加join
launch.start();
launch.join();
if (data.size()!=0) {
我建议你首先构建一个没有线程化工作的应用程序,然后从那一点开始添加多线程。
您在构造函数中传递的向量与您期望得到的向量相同。我认为,在Calculate
内,你应该有另一个向量来保存结果,当线程完成后,访问结果如:
launch.getResult()
Vector data=new Vector ();
//...
data = v;
从不使用在第一行创建的向量。 data = v
不会将v中的每个值复制到数据中。您可以使用:
data.addAll(v);
while (z.size()!=0) {
z.removeElementAt(0);
}
最好做z.clear();
答案 1 :(得分:0)
您的问题(可能)是在打印之前计算尚未完成。
看一下代码的这一部分:
launch.start();
if (data.size()!=0) {
System.out.println ("Delta: "+data.elementAt(0));
System.out.println ("Radice 1: "+data.elementAt(1));
System.out.println ("Radice 2: "+data.elementAt(2));
}
当你执行launch.start()时,计算开始但在其他线程中,并且此线程仍在运行,因此它开始打印数据Vector的元素。这些元素尚未更新。
尝试在Thread.sleep(2000);
之前添加if (data.size()!=0)
,看看结果是否会改变为您期望的结果。这样,在另一个打印输出之前,您将使一个线程完成它的工作。
这当然不是解决方案 - 它只会显示问题所在。如果你想要一个解决方案,请查看java.util.concurrent,你可以找到像CoundDownLatch这样有用的东西。
此外,您经常使用synchronized
关键字,而且并非必要。您应该始终小心使用synchronized
。
试试这本书:
http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601
但请记住,Java中的并发性是非常先进的主题。