Java中线程只能执行某些方法吗?

发布于 2024-10-21 19:35:25 字数 646 浏览 1 评论 0原文

我正在努力为机器人制作一个界面。我的机器人类具有包括移​​动、停止移动和读取传感器数据的方法。如果可能的话,我希望某些方法在给定线程下运行,某些其他方法在另一个线程下运行。我希望能够发送命令以移动到 robot 对象,让执行它的线程休眠 duration 毫秒,然后停止移动,但我希望可以调用 stop() 方法并中断正在执行运动的线程。非常感谢任何帮助。

public class robotTest
{

    public static void main(String[] args) throws InterruptedException
        {
            Robot robot = new Robot(); //Instantiate new Robot object
            robot.forward(255, 100, Robot.DIRECTION_RIGHT, 10); //Last argument representing duration
            Thread.sleep(5000); //Wait 5 seconds
            robot.stop(); //Stop movement prematurely

        }

}

I'm working on making an interface for a robot. My Robot class has methods that include movement, stopping movement and reading sensor data. If at all possible, I'd like to have certain methods run under a given thread and certain other methods run under another. I'd like to be able to send the command to move to the robot object, have the thread executing it sleep duration milliseconds and then stop movement, but I'd like the stop() method able to be called and interrupt the thread executing the movement. Any help is greatly appreciated.

public class robotTest
{

    public static void main(String[] args) throws InterruptedException
        {
            Robot robot = new Robot(); //Instantiate new Robot object
            robot.forward(255, 100, Robot.DIRECTION_RIGHT, 10); //Last argument representing duration
            Thread.sleep(5000); //Wait 5 seconds
            robot.stop(); //Stop movement prematurely

        }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

忆离笙 2024-10-28 19:35:25

我建议使用 ExecutorService 实例化您的 Robot 类,您可以使用它来异步移动。将移动请求提交到您的服务并使用返回的 Future 来“停止”移动请求。

class Robot{
    final ExecutorService movingService = Executors.newSingleThreadExecutor();
    private volatile Future<?> request; //you can use a Deque or a List for multiple requests
    public void forward(int... args){
         request = movingService.submit(new Runnable(){
               public void run(){
                      Robot.this.move(args);
               }
         });
    }
    public void stop(){
       request.cancel(true);
    }

}

I would suggest instantiating your Robot class with an ExecutorService that you can use for moving asynchronusly. Submit the movement request to your service and use the Future returned to 'stop' the move request.

class Robot{
    final ExecutorService movingService = Executors.newSingleThreadExecutor();
    private volatile Future<?> request; //you can use a Deque or a List for multiple requests
    public void forward(int... args){
         request = movingService.submit(new Runnable(){
               public void run(){
                      Robot.this.move(args);
               }
         });
    }
    public void stop(){
       request.cancel(true);
    }

}
盛夏已如深秋| 2024-10-28 19:35:25

如果我理解正确,那么是的,您可以从任何给定线程调用对象上的方法。然而,为了以无错误的方式工作,机器人类需要 线程安全

If I'm understanding you correctly then yes, you can call methods on an object from any given thread. However, for this to work in a bug free fashion the robot class needs to be thread safe.

爱的十字路口 2024-10-28 19:35:25

确保对 Robot 的所有调用都来自具有调用权限的线程(扩展您创建的 Thread 的类)。将此方法添加到您的调用中。

注意:这段代码远非完美。但它可能会给您一些可以在您的应用程序中使用的想法。

public void stop() throws NoPermissionException {

    checkStopPermission(); // throws NoPermissionException

    // rest of stop here as normal

}

/**
 * Alternatively you could return a boolean for has permission and then throw the NoPermissionException up there.
 */
private void checkStopPermission() throws NoPermissionException() {
    try {
        Thread t = Thread.currentThread();
        RobotRunnableThread rrt = (RobotRunnableThread)t; // may throw cast exception

        if(!rrt.hasPermission(RobotRunnableThread.STOP_PERMISSION)) { // assume Permission enum in RobotRunnableThread
            throw new NoPermissionExeception();
        }
    } catch(Exception e) { // perhaps catch the individual exception(s)?
        throw new NoPermissionException();
    }
}

Make sure all your calls to Robot come from a thread (a class extending Thread that you create) with permissions to make the calls. Add this method to your call.

Note: this code is far from perfect. But it may give you some ideas you can use in your application.

public void stop() throws NoPermissionException {

    checkStopPermission(); // throws NoPermissionException

    // rest of stop here as normal

}

/**
 * Alternatively you could return a boolean for has permission and then throw the NoPermissionException up there.
 */
private void checkStopPermission() throws NoPermissionException() {
    try {
        Thread t = Thread.currentThread();
        RobotRunnableThread rrt = (RobotRunnableThread)t; // may throw cast exception

        if(!rrt.hasPermission(RobotRunnableThread.STOP_PERMISSION)) { // assume Permission enum in RobotRunnableThread
            throw new NoPermissionExeception();
        }
    } catch(Exception e) { // perhaps catch the individual exception(s)?
        throw new NoPermissionException();
    }
}
留蓝 2024-10-28 19:35:25

当您实例化一个处理移动的 Robot 时,您必须启动一个新的后台线程。线程将坐在那里,等待来自转发或停止的信号并执行适当的操作。

您必须使用信号量、等待句柄或其他线程间通信元素来同步线程。

最不健壮的解决方案,浪费了最多的CPU(这是伪代码,因为我有一段时间没有使用Java,可能与.NET API混合在一起):(

public class Robot implements IRunnable {
    public Robot() {
       new Thread(this).Start();
    }

    private int direction = 0;
    private int duration = 0;
    private bool go = false;

    public void Run() {
        DateTime moveStartedAt;
        bool moving = false;
        while(true) {
            if(go) {
                if(moving) {
                    // we are already moving
                    if((DateTime.Now - moveStartedAt).Seconds >= duration) {
                        moving = false;
                    }
                } else {
                    moveStartedAt = DateTime.Now;
                    moving = true;
                }
            } else {
                moving = false;
            }
        }
    }

    public void forward(int direction, int duration) {
        this.direction = direction;
        this.duration = duration;
        this.go = true;
    }

    public void stop() {
        this.go = false;
    }
}

上面的代码应该修改为Java以获得更好的答案)

出了什么问题使用以下代码:

  • Run() 方法消耗整个 Core(它没有睡眠)
  • 立即调用 stop() 然后调用forward() 可能会导致竞争条件(Run() 尚未看到停止,但是您已经给了它另一个转发)
  • Run() 无法退出
  • 您可以调用forward() 来重定向已经在进行中的移动
  • 其他?

You have to start a new background thread when you instantiate a Robot that would handle movement. The thread would sit there, waiting for a signal from forward or stop and do the appropriate thing.

You will have to synchronize the threads using either semaphores, wait handles, or other inter thread communication elements.

The least robust solution that wastes the most CPU (this is pseudo code since I have not used Java in a while, might be intermixed with .NET APIs):

public class Robot implements IRunnable {
    public Robot() {
       new Thread(this).Start();
    }

    private int direction = 0;
    private int duration = 0;
    private bool go = false;

    public void Run() {
        DateTime moveStartedAt;
        bool moving = false;
        while(true) {
            if(go) {
                if(moving) {
                    // we are already moving
                    if((DateTime.Now - moveStartedAt).Seconds >= duration) {
                        moving = false;
                    }
                } else {
                    moveStartedAt = DateTime.Now;
                    moving = true;
                }
            } else {
                moving = false;
            }
        }
    }

    public void forward(int direction, int duration) {
        this.direction = direction;
        this.duration = duration;
        this.go = true;
    }

    public void stop() {
        this.go = false;
    }
}

(the above code should be modified to be Java for better answer)

What is wrong with this code:

  • The Run() method consumes one whole Core (it has no sleeps)
  • Calling stop() and then forward() right away can result in a race condition (the Run() has not seen the stop yet, but you already gave it another forward)
  • There is no way for Run() to exit
  • You can call forward() to redirect the move that is already in progress
  • Others?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文