ExecutorService中的线程是否可以在单独的线程上调用方法?

时间:2017-07-14 03:44:51

标签: java multithreading sockets server

我有一个套接字服务器,它使用ExecutorService为每个新套接字创建一个新线程。我还有一个类的静态实例,它使所有线程都使用数据库调用。

我的服务器用于在线国际象棋比赛。当用户进行移动时,移动被发送到服务器,并且在DB中输入关于移动的一般信息(包括匹配的ID)。每隔10秒左右,如果匹配的其他客户端也有一个活动套接字到服务器,它将要求服务器获取有关匹配的所有新数据。

它有效,但正如你可以想象的那样,如果连接了非平凡数量的玩家,效率会相当低。我想要的是一个线程窥视线程池并根据ID(使用该线程的客户端的ID)找到另一个线程的方法,然后调用该线程上的方法向该线程发送消息对手。

我一直在寻找,我没有运气。这样的事情可能吗?如果是,是否可取?即使代码有点危险,我也愿意采取额外措施来降低巨大的资源节约效益。

2 个答案:

答案 0 :(得分:0)

就像我在评论中所说,你的问题令人困惑;如果您尝试做的只是在玩家进行移动时通知对手,最简单的实现是使用BlockingQueue。 Javadoc甚至还有代码示例,因此应该很容易实现。在您的情况下,无论何时玩家进行移动,您都会将一个项目放入队列中,消费者会选择并通知参与同一游戏的对手。你不需要搞乱低级别的线程结构,如果你甚至想要根据池中的id找到线程,那你就错了。

BlockingQueue会起作用,但它涉及忙碌的等待,所以我不是它的忠实粉丝。相反,您可以使用Observer设计模式; JDK已经对此有所支持。以下是我编写的一个示例:

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.

最后但并非最不重要的是,如果您真的想要提升一个档次,请使用消息传递。你没有提到你是否正在使用一个框架(再次,你缺乏信息),但Spring支持消息传递,Akka,Play和Camel也是如此。

答案 1 :(得分:-1)

你可以创建ExecutorService,提供你自己的ThreadFactory,它能够创建你自己的istantiate类,它扩展了Thread并且引用了ThreadFactory本身。 ThreadFactory应该遍历所有创建的Thread并能够通过它们的ID识别它们。这样一来,每个Thread都能够在ThreadFactory中查询一些ID。