Java 中线程池的并发

Concurency at a thread pool in Java

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

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 的 class 有一个名为 Server s 的参数,它在创建线程的客户端任务 class 中传递它。客户端任务class是这样的:

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

如您所见,当请求到来时,将调用 class MyServer 的 handleRequest 方法。我想让这个方法 运行 同步,这意味着一次只有一个线程能够 运行 这个方法。在方法实现前加上synchronized 并没有起到任何作用。

任何人都可以给我正确的方法吗? 提前感谢您的宝贵时间。

PS: 我添加了整个代码

我的服务器Class http://pastebin.com/6i2bn5jj

多线程服务器Class 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 可以先执行。我想确保订单是在 main 中创建请求的订单。

But Instead the order is mixed. Sometimes Bye which shuts the server can be executed first. I want to ensure that the order is the one where the requests are created in the main.

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

要查看这是否是问题所在,我会删除 System.exit(0) 以查看其他行是否成功,就在 "Bye" 字符串之后。或者你可以在 exit(0).

之前放一个 Thread.sleep(5000);

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

就您原来的问题而言,由于竞争条件,锁定服务器无济于事。 "Bye" 可能会先成功并锁定服务器。

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

希望对您有所帮助。

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

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