【问题标题】:Concurency at a thread pool in JavaJava中线程池的并发性
【发布时间】:2017-07-18 14:25:03
【问题描述】:

我在 Java 中遇到了这个问题。 我有一个名为 MyServer 的服务器类,我想实现一个线程池,其中每个线程在请求​​到来时运行 MyServer 的方法。我创建了另一个实现名为 MultiThreadedSocketServer 的服务器池的类。类是这样的:

public class MultiThreadedSocketServer {

public void startServer(MyServer s, int localport, int threadPoolSize) {
    final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(threadPoolSize);

    Runnable serverTask = new Runnable() {
        @Override
        public void run() {
            try {
                ServerSocket serverSocket = new ServerSocket(localport);
                System.out.println("Waiting for clients to connect...");

                while (true) {
                    Socket clientSocket = serverSocket.accept();
                    clientProcessingPool.submit(new ClientTask(clientSocket, s));
                }
            } catch (IOException e) {
                System.err.println("Unable to process client request");
                e.printStackTrace();
            }
        }
    };
    Thread serverThread = new Thread(serverTask);
    serverThread.start();
}
}

名为 MultiThreadedSocketServer 的类有一个名为 Server 的参数,该参数将其传递给创建线程的客户端 Task 类。客户端任务类是这样的:

 class ClientTask implements Runnable {
    private final Socket clientSocket;
    private MyServer s;

    public ClientTask(Socket clientSocket, MyServer s) {
        this.s = s;
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        System.out.println("Got a client !");

        String inputLine = null;
        try {

        BufferedReader in =  new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        // Do whatever required to process the client's request
        inputLine = in.readLine();           

        if (inputLine.equals("Bye")) {
            System.out.println("Bye");
            System.exit(0);
        }

        s.handleRequest(inputLine);

            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

正如您所见,当请求到来时,MyServer 类的 handleRequest 方法被调用。我想让这个方法同步运行,这意味着一次只有一个线程能够运行这个方法。在方法实现之前添加同步不会实现任何目标。

谁能给我正确的方法来做到这一点? 提前感谢您的宝贵时间。

PS:我添加了整个代码

MyServer 类 http://pastebin.com/6i2bn5jj

多线程服务器类 http://pastebin.com/hzfLJbCS

正如在 main 中很明显,我创建了三个带有参数 Task、task2 和 Bye 的 handleRequest 请求。

正确的输出应该是

Waiting for clients to connect...
Got a client !
This is an input Task
Request for Task
Got a client !
This is an input task2
Request for task2
Got a client !
This is an input
Bye

但是顺序是混合的。有时可以先执行关闭服务器的 Bye。我想确保订单是主要创建请求的订单。

【问题讨论】:

  • 使MyServer.HandleReq()同步将防止多个线程同时在同一个MyServer实例上调用该方法。您有多少个 MyServer 实例?旁注:请尊重命名约定。
  • 只有一个 MyServer 实例将始终运行。抱歉,如果您想澄清,我不知道命名约定,我将编辑我的帖子
  • 方法以小写字母开头。 HandleReq 应该是handleReq,或者更好的是handleRequest。变量也一样。 ThreadPoolSize 应该是 threadPoolSize。如果您有一个 MyServer 实例,那么同步该方法就可以了。你如何测试它没有正确同步?
  • 在 handleRequest 方法中,我使用反射根据输入字符串调用 MyServer 类的不同方法。即使将此方法声明为同步,我在每次执行时都会得到不同的结果。调用的方法并不总是以正确的顺序调用,即输入到达服务器端口的顺序。
  • 同步并不能保证任何排序。我认为您是根据不正确的假设得出结论。如果您需要解释,您需要发布相关代码、示例输入和输出,并解释您希望代码做什么以及它会做什么。

标签: java multithreading concurrency server threadpool


【解决方案1】:

但是顺序是混合的。有时可以先执行关闭服务器的 Bye。我想确保订单是在主目录中创建请求的订单。

您说您希望服务器按顺序处理请求。这很难确保,因为您正在打开 3 个套接字并将它们写入服务器但不等待任何响应。这取决于实现,但我不确定当客户端从执行套接字InputStream 写入返回时,服务器是否已收到字节。这意味着从客户端来看,不能保证 IO 会按照您想要的顺序完成。

要查看这是否是问题所在,我将删除 System.exit(0) 以查看其他行是否成功,就在 "Bye" 字符串之后。或者,您可以在 exit(0) 之前添加一个 Thread.sleep(5000);

一种简单的解决方法是确保您的PrintStream 已打开自动刷新。这至少会在套接字上调用flush,但即便如此,客户端和服务器之间也会存在竞争条件。如果自动刷新不起作用,那么我会让您的客户端等待服务器的响应。因此,第一个客户端将编写第一个命令并等待确认,然后再执行第二个命令。

就您最初的问题而言,由于竞争条件,锁定服务器无济于事。 "Bye" 可能会先行锁定服务器。

这些关于如何在多线程程序中同步线程的问题对我来说真的没有意义。线程的全部要点是它们异步并行运行并且不必以任何特定顺序运行。你越是强迫你的程序以特定的顺序输出输出,你就越是主张在没有任何线程的情况下编写它。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    如果问题是bye 消息在处理其他请求之前终止了服务器,一种解决方案可能是不要在bye 上调用System.exit(0);

    bye 消息可以设置一个标志来阻止进一步的请求被处理,并且还可以通知其他机制在线程池空闲且没有请求处理时调用System.exit(0);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-12
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 2013-04-19
      • 2019-03-11
      • 1970-01-01
      • 2015-02-13
      相关资源
      最近更新 更多