[英]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.