【问题标题】:Accessing values from another thread从另一个线程访问值
【发布时间】:2013-04-13 16:40:24
【问题描述】:

我的问题是:如何从另一个线程访问值?

我有两个 .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() 方法中使用这些新值。

【问题讨论】:

标签: java multithreading kinect simple-openni


【解决方案1】:

要从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 关键字,这样只有一个线程可以同时调用此方法,否则会出现竞争条件。

【讨论】:

  • 应该使用java.util.concurrent中的对象在线程间传递值
  • 非常感谢你们的帮助!我想从 TrackHands 获得的值经常更新,我只需要最新的值(那些是你手上的 X 和 Y 坐标),所以我认为不需要锁。或者你推荐我使用它们吗? '对象输出;'行在第二行,我必须制作一个 Object 对象吗?或者这只是为了演示目的?因为我真的不知道如何给对象赋值,所以我可以从另一个线程获取它。
  • 如果您只需要最新的输入,则不需要锁定,您可以将 Object 设置为您想要的任何类型 - 这只是为了演示目的。
  • 你能帮我多一点吗?我能想到的唯一解决方案是创建一个具有两个 int 的另一个类和一个接受两个 int 参数并将它们初始化为两个 int 的构造函数。向新类添加一个 get 方法,并在我要使用输入的类中调用 get 方法。然后创建对象并将值传递给它。但我认为有一个我想不出的更简单、更合乎逻辑的解决方案。
  • 另一种选择是使用两个 get 方法,每个 int 一个。或者使用一种返回 int 数组/数组列表的 get 方法。
【解决方案2】:

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

我要感谢所有帮助我的人!

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多