2016-10-05 70 views
2

以下是接受客戶端套接字連接併爲每個連接分配線程的代碼(JAVA)。JAVA多線程服務器插座

ServerSocket m_ServerSocket = new ServerSocket(); 

while (true) { 
      java.util.Date today = Calendar.getInstance().getTime(); 
      System.out.println(today+" - Listening to new connections..."); 

      Socket clientSocket = m_ServerSocket.accept(); 
      ClientServiceThread cliThread = new ClientServiceThread(clientSocket); 
      cliThread.start(); 
} 

假設有5個客戶端連接,因此有5個線程正在運行。

client 1: threadId 11 
client 2: threadId 12 
client 3 :threadId 13 
client 4 :threadId 14 
client 5 :threadId 15 

假設一個客戶端發送消息「殺 - 客戶端1」,我希望最終客戶1的連接,並殺死線程ID爲11,像這樣:

public void run() { 
    try { 
    BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 
    PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream())); 

    while (running) { 
    String clientCommand = in .readLine(); 

    if (clientCommand.equalsIgnoreCase("Kill-client1")) { 
     // end the connection for client 1 & kill it's corresponding thread 11 
    } 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} 
} 

我怎樣才能做到這一點?

+0

所以你basicly想爲客戶能夠殺死其他客戶端:) – Antoniossss

+0

@Antoniossss是的,先生。 –

回答

1

只需跟蹤所有客戶端套接字和/或處理線程。

Map<Integer,Socket> clients=new HashMap<>(); 

while (true) { 
      java.util.Date today = Calendar.getInstance().getTime(); 
      System.out.println(today+" - Listening to new connections..."); 

      Socket clientSocket = m_ServerSocket.accept(); 
      clients.put(generateNewClientId(),clientSocket); 
      ClientServiceThread cliThread = new ClientServiceThread(clientSocket); 
      cliThread.start(); 
} 

,然後如果你簡單地做

{ 
    if (clientCommand.equalsIgnoreCase("Kill")) { 
     Socket socket=clients.get(idToShutDown);// get required id somehow (from request??) 
     socket.close(); 
    } 
} 

這將關閉給定的套接字導致處理線程從而完成線程打破in.readLine()

如果您跟蹤線程,您可以設置「中斷」標誌並在while條件中進行探測,以便您的處理線程能夠優雅地完成工作。

+0

似乎這讓我更接近,讓我試試謝謝!如果這有效,我會接受答案。 –

+0

我決定使用你的答案邏輯和@Nicolas Filottoanswer的組合。謝謝 ! –

0

要停止當前線程,你close the socket,並從運行返回()方法:

if (clientCommand.equalsIgnoreCase("Kill")) { 
    clientSocket.close(); 
    return; 
} 

編輯:

關閉另一個線程,你可以,例如

  • 在線程之間共享clientID-Thread條目的線程安全映射。當一個新的客戶端連接時,你在這張地圖上存儲爲這個客戶端啓動的線程
  • 當一個Kill-client1命令進來時,你得到線程從地圖上相應的「client1」鍵,並且在這個地方調用nterrupt()線。
  • 在每個線程(例如,client1線程)中,在循環的每次迭代中,檢查Thread.currentThread()。isInterrupted()的值。如果是,則關閉連接,從共享映射中刪除線程,然後從run()方法中返回。

關鍵是你永遠不會殺死另一個線程。您總是通過中斷來請求線程停止,並且線程檢查中斷標誌的值以決定何時以及如何停止。

+0

我不想讓線程自己殺死,而是我想要其他線程或者父進程根據線程ID來殺死它。 –

+0

然後你應該澄清你的問題,因爲那還不清楚。線程如何根據命令「Kill」知道要殺死哪個線程? –

+0

是的你是對的讓我編輯我的問題,但請幫助 –

0

就終止循環:

while (running) { 
    String clientCommand = in .readLine(); 

    if (clientCommand.equalsIgnoreCase("Kill")) { 
     running = false; 
    } 
    } 

或:

while (running) { 
    String clientCommand = in .readLine(); 

    if (clientCommand.equalsIgnoreCase("Kill")) { 
     break; 
    } 
    } 

而且不要忘記關閉插座finally塊。

+0

我不希望線程自己殺死,而是我想要其他線程或可能父進程殺死它基於線程ID –

1

你可以做到這一點通過使用線程ID爲重點

// Map that will contain all my threads 
Map<Long, ClientServiceThread> threads = new ConcurrentHashMap<>(); 

// Add to the constructor the instance of the class that manage the threads 
ClientServiceThread cliThread = new ClientServiceThread(this, clientSocket); 
// Add my new thread 
threads.put(cliThread.getId(), cliThread); 
cliThread.start(); 

然後當一個kill啓動存儲您Threads線程安全的地圖(因爲它會由多個線程同時訪問)

String clientCommand = in.readLine().toLowerCase(); 
if (clientCommand.startsWith("kill")) { 
    main.interrupt(Long.valueOf(clientCommand.substring(4).trim())); 
} 

然後在主類的方法將是這樣的:

public void interrupt(long threadId) { 
    // Remove the thread from the map 
    ClientServiceThread cliThread = threads.remove(threadId); 
    if (cliThread != null) { 
     // Interrupt the thread 
     cliThread.interrupt(); 
    } 
} 

最後,你將需要ClientServiceThread類敏感中斷

try { 
    ... 
    while (!Thread.currentThread().isInterrupted()) { 
     // My code here 
    } 
} finally { 
    clientSocket.close(); 
} 
+0

我決定使用你的答案邏輯和@Antoniossss答案的組合。謝謝 ! –