1

我对 Java 有点陌生,所以还没有完全掌握多线程的概念。我想创建一个 PIDController 类来允许我这样做:

ControllerMethods methods = new ControllerMethods()
                            {
                                public long getError(long setpoint)
                                {
                                    //get an input
                                }
                                public void setOutput(long value)
                                {
                                    //do something
                                }
                                public void isComplete(long setpoint)
                                {
                                    return getError() == 0;
                                }
                            };

PIDController motorPID = new PIDController(setpoint, kp, ki, kd, methods);

motorPID.run();
//runs the PID controller to completion (methods.isComplete() == true)

motorPID.run(false);
//starts the PID controller in a separate thread, allowing
//continual monitoring in the current thread

while(motorPID.isRunning())
{
    //do something else
    if(condition1)
        motorPID.pause();
        //pause the PID controller, preventing the integral from increasing
    else if(condition2)
        motorPID.stop();
}

我已经弄清楚了如何计算标准 PID 算法,但我不知道如何提供异步功能。

谁能告诉我如何实现类似的 API?

4

2 回答 2

1

您已经实现了一个run()方法,PIDController因此您还应该实现Runnable接口:

class PIDController implements Runnable {
    ....
}

现在你可以通过调用来启动你的 PIDController 异步:

pidControllerThread = new Thread( pidController );
pidControllerThread.start();

对于同步(如果需要),您应该查看 sun concurrency guide

于 2009-10-25T09:28:09.773 回答
0

到目前为止,将线程附加到任何事物的最佳机制是将执行工作的对象与作为线程的对象分开。Runnable 接口可能很有吸引力,因为它允许人们将对象传递给 Thread 构造函数或 Executor,并运行它。但是,如果您对对象的生命周期管理要求超出了“运行到完成”的范围,例如暂停,那么在大多数情况下,您会发现管理对象中的线程更合适,以便您知道哪个线程正在运行(是的,您可以在进入运行时将实例对象设置为 Thread.currentThread(),但是......)。

所以,我认为你所拥有的是一个好的开始。您需要添加一些锁定来帮助自己管理 pause() 和其他线程控制。

    公共类 PIDController {
        私有最终对象 myLock = new Object();
        私有最终控制器方法 ctrl;
        私有 volatile Thread 线程;
        私人 volatile Runner 亚军;
        私人 int pidInterval = 700;
        私有最终双 setPoint,kp,ki,kd;

        公共PIDController(双setPoint,双kp,双ki,双kd,ControllerMethods inst){
            this.ctrl = inst;
            this.setPoint = setPoint;
            这个.kp = kp;
            这个.ki = ki;
            这个.kd = kd;
        }

        公共无效暂停(){
            同步(我的锁){
                如果(跑步者。暂停){
                    throw new IllegalOperationException(this+": 已经暂停");
                }
                runner.paused = true;
            }
        }

        公共无效简历(){
            同步(我的锁){
                如果(!runner.paused){
                    throw new IllegalOperationException(this+": 已经恢复");
                }
                runner.paused = false;
            }
        }

        公共布尔isRunning(){
            返回运行;
        }

        公共无效开始(){
            如果(线程!= null){
                throw new IllegalOperationException(this+": already running");
            }
            我的线程 = 新线程(亚军 = 新亚军());
            myThread.start();
        }

        公共无效停止(){
            如果(跑步者==空){
                throw new IllegalOperationException(this+": PID is not running");
            }
            runner.running = false;
            如果(跑步者.暂停)
                恢复();
            跑步者=空;
        }


        // 重要的是,无论何时实现可停止的 Runnable,
        // 您将“运行”标志作为内部实例类的成员包括在内,例如
        // 这样当你要求这个实例停止时,你可以立即重启
        // 另一个实例并且没有两个线程观察相同的“运行”标志
        私有类 Runner 实现 Runnable {
            volatile bool running = false,bool 已暂停;
            公共无效运行(){
                运行=真;
                在跑步的时候 ) {
                    // 在循环顶部执行此操作,以便从
                    // pause 将在重新计算之前检查运行。
                    重新计算PID();

                    // 使用双重检查习语
                    如果(暂停){
                        同步(我的锁){
                            而(暂停){
                                myLock.wait();
                            }
                        }
                    }
                    Thread.sleep(pidInterval);
                }
            }
        }

        公共无效重新计算PID(){
            ...
        }
    }

于 2015-05-28T02:24:34.480 回答