简体   繁体   中英

Java: sharing a vector between 2 classes

I'm writing an application that calculates delta and roots of a second degree equation, accepting its coefficients as input. Later, i want to give it a GUI.

This is the class that calculates everything:

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) {}
}
}

which i tested and is working well. The problem is in the test code i wrote for it:

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));
    }
}
}

and specifically in the output for Delta. In facts, roots are correctly shown, but instead of delta, it prints the a coefficient (by example, if i pass 1 1 -6, i expect delta to be 25, but it shows 1; if it s 2 2 -12 delta hould still be 25, but it shows 2). Somehow, the first element of this vector doesn't get deleted and replaced, but i don't know why; i just know it's not a matter of synchronisation, since i tried to delete all of the syncs and the output was the same.

So, what's my mistake? Thank you.

What's the point of all the multi-threading stuff ?

synchronized (data) {

This synchronize an object that you'll never use later

launch.start();
if (data.size()!=0) {

You don't even wait the thread to finish before using the data, try to add join

launch.start();
launch.join();
if (data.size()!=0) {

I suggest you first build an application that works without the threading stuff, then add multi-threading from that point.

I think it's a bad practice to have the same object hold the input and the output

The vector that you pass in the constructor is the same than the one you're expecting the result from. I think, inside Calculate , you should have another vector to hold the result, and when the thread has finished, access the result like:

launch.getResult()

Some code improvements

Vector data=new Vector ();
//...
data = v;

the vector created on the first line is never used. data = v doesn't copy each values from v into data. You can use:

data.addAll(v);

while (z.size()!=0) {
    z.removeElementAt(0);
}

Better do z.clear();

Your problem is (probably) that the calculations haven't finished before you print them.

Take a look at this part of your code:

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));
}

When you do launch.start() the calculations start but in other thread, and this thread is still runing, so it starts to print the elements of data Vector. And those elements weren't updated yet.

Try adding Thread.sleep(2000); before the if (data.size()!=0) and see if the results change to what you would expect. This way you will make one thread to finish it's job before the other one prints the output. This is not the solution of course - it will only show where the problem lies. If you want a solution look at java.util.concurrent and there you can finds something useful like CoundDownLatch.

Moreover you're using the synchronized keyword much to often and not necessarly proper. You should be always careful with using synchronized . Try this book:

http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601

but keep in mind that concurrency in Java is quite advanced subject.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM