开发者

Can a thread only execute certain methods in Java?

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

        }

}


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

}


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.


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


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?
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜