繁体   English   中英

Java中线程池的并发性

[英]Concurency at a thread pool in Java

我在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

正如在主文件中显而易见的那样,我使用带有参数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。 我要确保订单是在主订单中创建请求的订单。

但是相反,顺序是混杂的。 有时,可以先执行关闭服务器的Bye。 我要确保订单是在主订单中创建请求的订单。

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

要查看这是否是问题,我将删除System.exit(0)以查看是否其他行成功实现了, "Bye"字符串之后。 或者你可以放一个Thread.sleep(5000); exit(0)

一个简单的排序修补程序是确保您的PrintStream启用了自动刷新功能。 至少这将在套接字上调用flush,但是即使那样,客户端和服务器之间仍存在竞争条件。 如果自动刷新不起作用,那么我会让您的客户端等待服务器的响应。 因此,第一个客户端将编写第一个命令并等待确认,然后再转到第二个命令。

就您最初的问题而言,由于竞争条件,锁定服务器并没有帮助。 "Bye"可能会使其先行并锁定服务器。

关于如何在多线程程序中同步线程的这类问题对我来说真的没有任何意义。 线程的全部要点是它们可以异步并行运行,而不必按任何特定顺序进行操作。 强迫程序以特定顺序吐出输出的内容越多,则争用无线程编写输出的争论就越多。

希望这可以帮助。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM