Razor Storm
Razor Storm

Reputation: 12336

How are a java Runnable object's other methods called?

I am given some skeletons of classes that I must implement (I personally don't really agree with the design of the program but I am not at mercy to change it :( ) and they work in this manner:

I have a Game class which implements Runnable and represents a chess game.

A Server class will have a list of multiple Game classes that it keeps track of.

Ok this makes sense, Game implements Runnable so the Server can put each game in its own thread.

I am a bit confused at how java's threads work.

What I know is the following:

After tying my Runnable class to a thread and calling the .start() method, the Runnable class's run() method is called.

However, I have some other methods inside my Game class such as:

capturePiece()

playerMakesMove()

etc

In the current design, it is up to the Server to handle game actions. When a player wants to capture a piece, the Server will call game.capturePiece().

In this case, is capturePiece() being run on the Game thread, or the Server's thread? (the caller's thread or the callee's thread)

In this case, what would run() even do?

Upvotes: 3

Views: 3026

Answers (3)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

@Razor, as per other discussion, if a class implements Runnable and the run method is tied up with a long running process, you can still call other methods of the class. And this can be tested like this:

public class TestThreads {
   public static void main(String[] args) {
      TestGame testGame = new TestGame();
      new Thread(testGame).start();

      for (int i = 0; i < 10; i++) {
         testGame.otherMethod();
         try {
            Thread.sleep(1000);
         } catch (InterruptedException e) {}
      }
      System.out.println("done");
      System.exit(0);
   }
}

class TestGame implements Runnable {
   @Override
   public void run() {
      try {
         Thread.sleep(100 * 1000);
      } catch (InterruptedException e) {}
   }

   public void otherMethod() {
      System.out.println("in other method");
   }
}

Upvotes: 5

Miserable Variable
Miserable Variable

Reputation: 28752

Any method, in any programming language, executes in the same thread as the caller. When you call Thread.start() it runs in the same thread that called it.

Now, you know that the run() method of a Thread does not execute in the same thread as start. But that is because start does not itself call run. You will have to read up more on threads to get the complete picture but just imagine that start only crates a new thread with some data structure (the Runnable) and the newly created thread looks at that data structure, identifies the Runnable and executes its run method.

And that is really the only way control passes from one thread to another: one thread generates some data and other thread picks it up and processes it. Control does not pass from one thread to another, it is inter-thread communication and co-ordination.

If the methods of Game are called by Server then the threads are not going to have anything to do, are they? But instead, if the Server does not call the method directly but instead represents the action as data then Game.run() can pick the action and perform it, in its own thread.

Now the only question is where can Server put the data such that each Game.run(), running in its own thread knows to pick it up from. One option is to use BlockingQueue. The Server can put these Action objects in the queue and the Game thread can pick it up. How will the two know to use the same queue? There many different ways, one is for server to create the game with a queue and store a map on its side. As in the skeleton below:

class Server {
    Map<Game, BlockingQueue> games = ....;

    void createGame() {
        BlockingQueue queue = ....;
        Game game = new Game(queue);
        games.put(game, queue);
    }

    void foo() {
       Game game = ....; 
       Action action = ....; // identify the Game
       map.get(g).add(action);
    }
}

class Game {
    BlockingQueue _queue;

    Game(BlockingQueue queue) { 
         _queue = queue; 
    }

    void run() {
        while (true) {
            Action nextAction = _queue.take();
            // perform the action
        }
    }
}

Upvotes: 6

Heisenbug
Heisenbug

Reputation: 39164

In this case, is capturePiece() being run on the Game thread, or the Server's thread?

capturePiece will run on the Game thread, where the method has been called.

In this case, what would run() even do?

If it always the Server who calls method on Game threads, then you could do the same with a single thread. Threads will be useful if the actions were triggered by each Game thread that independently call Server to notify the result.

Upvotes: 2

Related Questions