0

I have a socket server that uses an ExecutorService to create a new thread for each new socket. I also have a static instance of a class that makes database calls that all threads use.

My server is used for online chess matches. When a user makes a move, the move is sent to the server and an entry is made in the DB with general information about the move (including the ID of the match). Every 10 seconds or so, if the match's other client also has an active socket to the server, it will ask the server to fetch all new data about the match.

It works, but as you can imagine gets pretty inefficient if a non-trivial number of players are connected. What I want is a way for a thread to peek into the thread pool and find another thread based off an ID (The ID of the client for whom the thread is used), then call a method on that thread to send a message to the opposing player.

I've been looking all over, and I've had no luck. Is such a thing possible? If it is, is it advisable? Even if it's a bit risky code-wise, I'm willing to take extra steps to mitigate the risk for the enormous resource-saving benefits.

  • 3
    Methods belong to classes/objects not threads. What you need is a way to signal between the 2 players/threads that a move has been made. Think of the two clocks when one player presses the button, the other needs to move – bichito Jul 14 '17 at 03:51
  • two atomic/volatile booleans in the player class should do the trick for you – bichito Jul 14 '17 at 03:57
  • 1
    Get the DB out of the way. It is only useful if you want to recreate the match later. The players only need the opponent's last move and maybe even the booleans are extra. – bichito Jul 14 '17 at 04:05
  • Yes this post confused me since uncalled methods don't exist in threads -- it makes no sense I'm afraid, and do you can't call a method from one thread on a separate thread. This construct just doesn't exist. – Hovercraft Full Of Eels Jul 14 '17 at 04:14
  • 1
    Yes. It catches you by surprise until one figures out that it is not possible. – bichito Jul 14 '17 at 04:22
  • Your question is interesting but confusing. First you say that every 10s, the opponent's thread polls the server. Later you say that you want to send a message to the other player. You need to explain what data is being polled, and what message you want to send. Don't worry about thread stuff for now. – Abhijit Sarkar Jul 14 '17 at 05:01
  • @HovercraftFullOfEels What do you mean? If your Player class extends Thread you can have all the method you need and there's nothing that prevents threads to call methods of a separate threads. – ugo Jul 14 '17 at 16:08
  • @ugo: a Player class should *never* extend Thread, and even if it did, it can have methods called in threads other than "itself". Your statement above, "threads to call methods of a separate thread" again is meaningless. – Hovercraft Full Of Eels Jul 14 '17 at 16:22
  • @HovercraftFullOfEels as Thread is not final, why do you say tha a class should never extend Thread? Look at https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html theres There's an example that explain how to create a new thread: "class PrimeThread extends Thread", that's the official documentation, not my thought. – ugo Jul 14 '17 at 16:52
  • @ugo: Please look at the answers to [this question](https://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread) as well as [this question](https://stackoverflow.com/questions/15471432/why-implements-runnable-is-preferred-over-extends-thread) regarding why it is generally frowned up to extend Thread. – Hovercraft Full Of Eels Jul 14 '17 at 18:04
  • @HovercraftFullOfEels I did read and fully agree, expecially in making distinction between jab and and run. But this is the case where a job is needed, so a thread is advisable. – ugo Jul 14 '17 at 21:07

2 Answers2

0

Like I said in my comment, your question is confusing; if all you're trying to do is to notify the opponent when a player makes a move, the simplest implementation is to use a BlockingQueue. The Javadoc even has code examples, so it should be fairly easy to implement. In your case, whenever a player makes a move, you put an item in the queue, that the consumer picks up and notifies the opponent that is participating in the same game. You don't need to mess with low level thread constructs, and if you're even thinking of finding threads based on ids from a pool, you're doing it all wrong.

The BlockingQueue would work, but it involves busy wait, so I'm not a big fan of it. Instead, you can use the Observer design pattern; the JDK already has support for this. Following is an example that I made up:

public class Main extends Observable implements Observer {
    private final int numCores = Runtime.getRuntime().availableProcessors();
    private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);

    public Main() {
        addObserver(this);
    }

    public static void main(String[] args) throws InterruptedException {
        new Main().execute();
    }

    private void execute() {
        for (int i = 0; i < 5; ++i) {
            this.setChanged();
            this.notifyObservers(i);

            try {
                Thread.sleep(1000l);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        executor.shutdown();
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.printf("Received notification on thread: %s.\n", Thread.currentThread().getName());
        executor.submit(() -> System.out.printf("Running in thread: %s, result: %s.\n",
                Thread.currentThread().getName(), arg));
    }
}

Received notification on thread: main.
Running in thread: pool-1-thread-1, result: 0.
Received notification on thread: main.
Running in thread: pool-1-thread-2, result: 1.
Received notification on thread: main.
Running in thread: pool-1-thread-3, result: 2.
Received notification on thread: main.
Running in thread: pool-1-thread-4, result: 3.
Received notification on thread: main.
Running in thread: pool-1-thread-5, result: 4.

Last but not the least, if you really want to take it up a notch, use messaging. You didn't mention if you're using a framework (again, lack of information on your part), but Spring supports messaging, so does Akka, Play and Camel.

Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
-1

You may create the ExecutorService supplying your own ThreadFactory able to create your istantiate your own class that extends Thread and has a reference to the ThreadFactory itself. The ThreadFactory should trak all created Thread and be able to identify them by their ID. Such a way, each Thread will be able to query the ThreadFactory for some ID.

ugo
  • 284
  • 1
  • 2
  • 10
  • And which object inside the thread are you planning to use to invoke the method? – bichito Jul 14 '17 at 04:08
  • The ThreadFactory itself, that knows all the thread and their state, and each thread has a reference of it to ask about other thread, as I said. Is there anything you saw from the height of your reputation? If not, did you lowered my reputation just because youre shortsighted enough to misunderstand? Ask 1st, then decide. – ugo Jul 14 '17 at 06:31
  • Please read the comments and understand the question. You are confusing thread state with chess match progress. Which method in the thread class gives you a chess match instance? – bichito Jul 14 '17 at 11:52
  • If you have the player handler why do you need anything else? You do not need thread ids. Not even a queue. A queue in this case is like an 18 wheeler for commuting. Both player handlers synchronize on a little class that has last move position, piece and player. You are better off deleting the answer. – bichito Jul 14 '17 at 15:26
  • The question is: "What I want is a way for a thread to peek into the thread pool and find another thread based off an ID (The ID of the client for whom the thread is used), then call a method on that thread to send a message to the opposing player." The thread pool is the ThreadFactory itself, with methods to handle a game made of 2 opponents, with one palyerID each, that share the same game ID. Thus, the thread pool will implement an interface, known by players, with methods to enable opponents of the same game to communicate each other. Character exhausted, to be continued nex episode. – ugo Jul 14 '17 at 15:31
  • I need some more thet keep track of games, suppose that the 2 opponent threads didn't start at the same time, or for some reason the socket of one player stops, you need a mechanism to syncronize the players into the same game. Or must the game stop as well? – ugo Jul 14 '17 at 15:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/149236/discussion-between-ugo-and-efekctive). – ugo Jul 14 '17 at 15:40
  • 1
    There is no discussion here. Sorry, please read some basic threading books – bichito Jul 14 '17 at 15:42
  • Sorry, stackoverflow advised to move to a chat. Since I started working, about 40 years ago, I did read and write books. Goodbye. – ugo Jul 14 '17 at 15:56
  • @efekctive That's fairly constructive of you. Rude at best. – Zizouz212 Jul 15 '17 at 03:44