从另一个线程访问值

时间:2013-04-13 16:40:24

标签: java multithreading kinect simple-openni

我的问题是:如何从其他线程访问值?

我有两个.java文件,Main.java和TrackHands.java

Main.java

/**
 * This is the main class, it is used to start the program. The only use of this
 * is to make everything more organized.
 */
package Kinect;

//import processing.core.PApplet;
/**
 * @author Tony Nguyen <Tony.Nguyen@HvA.nl>
 *
 */
public class Main
{

    public static void main(String _args[])
    {  
        Thread trackHands = new Thread(new TrackHands());
        trackHands.start();
    }
}

TrackHands.java

/*
 * This uses the normal Java layout to track the user and prints out the coordinates of the left and right hand
 */
package Kinect;

import SimpleOpenNI.*;
import processing.core.PApplet;
import processing.core.PVector;

/**
 * @author Tony Nguyen <Tony.Nguyen@HvA.nl>
 * @version 1.0
 */
public class TrackHands extends PApplet implements Runnable
{

    private int handLeftX, handLeftY = 0; // Holds the coordinates of the left hand
    SimpleOpenNI kinect = new SimpleOpenNI(this); // kinect object

    /**
     * Constructor Takes no parameters
     */
    public TrackHands()
    {
    }

    /**
     * run This will be executed when the thread starts
     */
    @Override
    public void run()
    {
        IntVector userList = new IntVector(); // Make a vector of ints to store the list of users        
        PVector leftHand = new PVector(); // Make a vector to store the left hand
        PVector convertedLeftHand = new PVector();

        kinect.enableDepth();
        kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_ALL);
        kinect.setMirror(true);

        while (true)
        {
            kinect.update();

            kinect.getUsers(userList); // Write the list of detected users into the vector

            if (userList.size() > 0) // Checks if a user is found
            {
                int userId = userList.get(0); // Get first user

                if (kinect.isTrackingSkeleton(userId)) // If successfully calibrated
                {
                    kinect.getJointPositionSkeleton(userId,
                            SimpleOpenNI.SKEL_LEFT_HAND, leftHand); // Put the position of the left hand into that vector

                    kinect.convertRealWorldToProjective(leftHand,
                            convertedLeftHand);

                    this.handLeftX = round(convertedLeftHand.x);
                    this.handLeftY = round(convertedLeftHand.y);
                }
            }
        }

    }

    // User-tracking callbacks!
    public void onNewUser(int userId)
    {
        System.out.println("Start pose detection");
        kinect.startPoseDetection("Psi", userId);
    }

    public void onEndCalibration(int userId, boolean successful)
    {
        if (successful)
        {
            System.out.println("  User calibrated !!!");
            kinect.startTrackingSkeleton(userId);

        } else
        {
            System.out.println("  Failed to calibrate user !!!");
            kinect.startPoseDetection("Psi", userId);
        }
    }

    public void onStartPose(String pose, int userId)
    {
        System.out.println("Started pose for user");
        kinect.stopPoseDetection(userId);
        kinect.requestCalibrationSkeleton(userId, true);
    }
}

我尝试使用getter和setter将TrackHands.java中的值转换为另一个线程。 尝试创建对象并将值作为参数传递,但我的程序将不会在run()方法中使用这些新值。

2 个答案:

答案 0 :(得分:2)

要从TrackHands获取值,请使用get方法访问run()中设置的实例变量

class TrackHands {
    Object output;

    public void run() {
        while(true) {
            output = new Object();
        }
    }

    public Object getOutput() {
        return output;
    }
}

TrackHands传递到您的使用者对象,并使用它来调用get getOutput()方法。

传递值有点棘手,因为您可能会导致race condition。试试这样的事情

class TrackHands {
    Object input = null;
    public boolean setInput(Object input) {
        if(this.input == null) {
            this.input = input;
            return true;
        } else {
            return false;
        }
   }
}

run()方法使用input时,将其设置为null,以便另一个线程可以传入另一个输入。您的生产者线程将使用此循环传入输入:

public void sendInput(TrackHands th, Object input) {
    boolean done = false;
    while(!done) {
        done = th.setInput(input);
    }
}

这将继续尝试传递input直到成功。

setInput使用synchronized关键字,这样只有一个线程可以同时调用此方法,否则您将获得竞争条件。

答案 1 :(得分:0)

我的一个朋友解决了我的问题。

我要感谢大家帮助我!

<强> Main.java

/**
 * This is the main class, it is used to start the program. The only use of this
 * is to make everything more organized.
 */
package Kinect;

//import processing.core.PApplet;
/**
 * @author Tony Nguyen <Tony.Nguyen@HvA.nl>
 *
 */
public class Main
{

    public static void main(String _args[])
    {
//        PApplet.main(new String[]
//                {
//                    Sensor.class.getName()
//                });

        ValueStore valueStore = new ValueStore(); // ADDED THIS LINE
        Thread trackHands = new Thread(new TrackHands(valueStore)); // ADDED THIS LINE
        trackHands.start();
    }
}

TrackHands.java

/*
 * This uses the normal Java layout to track the user and prints out the coordinates of the left and right hand
 */
package Kinect;

import SimpleOpenNI.*;
import processing.core.PApplet;
import processing.core.PVector;

/**
 * @author Tony Nguyen <Tony.Nguyen@HvA.nl>
 * @version 1.0
 */
public class TrackHands extends PApplet implements Runnable
{

    private int handLeftX, handLeftY, handRightX, handRightY = 0; // Holds the coordinates of the left hand
    SimpleOpenNI kinect = new SimpleOpenNI(this); // kinect object
    private ValueStore valuesStore; // ADDED THIS LINE

    /**
     * Constructor Takes no parameters
     */
    public TrackHands()
    {
    }

    public TrackHands(ValueStore valuesStore)
    {
        this.valuesStore = valuesStore;
    }

    /**
     * run This will be executed when the thread starts
     */
    @Override
    public void run()
    {
        IntVector userList = new IntVector(); // Make a vector of ints to store the list of users        
        PVector leftHand = new PVector(); // Make a vector to store the left hand
        PVector rightHand = new PVector(); // Make a vector to store the right hand
        PVector convertedLeftHand = new PVector(); // Make a vector to store the actual left hand
        PVector convertedRightHand = new PVector(); // Make a vector to store the actual right hand

        kinect.enableDepth();
        kinect.enableUser(SimpleOpenNI.SKEL_PROFILE_ALL);
        kinect.setMirror(true);

        while (true)
        {
            kinect.update();

            kinect.getUsers(userList); // Write the list of detected users into the vector

            if (userList.size() > 0) // Checks if a user is found
            {
                int userId = userList.get(0); // Get first user

                if (kinect.isTrackingSkeleton(userId)) // If successfully calibrated
                {
                    kinect.getJointPositionSkeleton(userId,
                            SimpleOpenNI.SKEL_LEFT_HAND, leftHand); // Put the position of the left hand into that vector

                    kinect.getJointPositionSkeleton(userId,
                            SimpleOpenNI.SKEL_RIGHT_HAND, rightHand); // Put the position of the left hand into that vector

                    kinect.convertRealWorldToProjective(leftHand,
                            convertedLeftHand);

                    kinect.convertRealWorldToProjective(rightHand,
                            convertedRightHand);

                    this.handLeftX = round(convertedLeftHand.x);
                    this.handLeftY = round(convertedLeftHand.y);
                    this.handRightX = round(convertedRightHand.x);
                    this.handRightY = round(convertedRightHand.y);

                    valuesStore.setHandValues(handLeftX, handLeftY, handRightX, handRightY); // ADDED THIS LINE
                }
            }
        }

    }

    // User-tracking callbacks!
    public void onNewUser(int userId)
    {
        System.out.println("Start pose detection");
        kinect.startPoseDetection("Psi", userId);
    }

    public void onEndCalibration(int userId, boolean successful)
    {
        if (successful)
        {
            System.out.println("  User calibrated !!!");
            kinect.startTrackingSkeleton(userId);

        } else
        {
            System.out.println("  Failed to calibrate user !!!");
            kinect.startPoseDetection("Psi", userId);
        }
    }

    public void onStartPose(String pose, int userId)
    {
        System.out.println("Started pose for user");
        kinect.stopPoseDetection(userId);
        kinect.requestCalibrationSkeleton(userId, true);
    }
}

然后添加了一个类来存储值,以便另一个类可以访问它。

<强> ValueStore.java

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Kinect;

/**
 *
 * @author Tony Nguyen <Tony.Nguyen@HvA.nl>
 */
public class ValueStore
{

    private int leftX, leftY, rightX, rightY = 0;

    public void setHandValues(int leftX, int leftY, int rightX, int rightY)
    {
        this.leftX = leftX;
        this.leftY = leftY;
        this.rightX = rightX;
        this.rightY = rightY;
    }

    public int getLeftX()
    {
        return this.leftX;
    }
}