2017-05-30 86 views
-1

我有以下一段代碼,它從套接字讀取一個字符串並對其進行處理。從套接字讀取字符串後,我正在創建一個新線程來處理請求。這樣,我可以有多個線程同時處理傳入的請求。如何使用多線程從套接字讀取請求

public void process(Socket socket) throws Exception { 
    while (true) { 
     String request = readFromSocket(socket); 
     new Thread(() -> { 
      try { 
       System.out.println(request); // [edit]: I had omitted this line before as I thought it would be irrelevant 
       response = processRequest(request); // <-- request could get modified 
      } catch (Exception e) { 
       // TODO: Log error and print stack-trace 
      } 
     }).start(); 
    } 
} 

這裏的問題是,「請求」可能會在新線程開始處理它之前被修改。我是多線程的新手,我讀了幾個涵蓋基礎知識的網站。我仍然不確定如何解決這裏的問題。

使用synchronized函數等待新線程完成處理請求將會終止多線程的目的。一旦我得到請求,我想將它發送到一個新的線程,以便它可以開始處理請求,而父線程可以讀取下一個請求。

任何幫助我如何解決這個問題?謝謝!

[盧克的回答後編輯]

在我的情況下,請求將是一個文件名。您可以根據目錄的大小獲取多個請求。當我在一個文件較少的目錄上嘗試我的代碼時,一切都很好。但是當我用一個有數千個文件的目錄運行我的代碼時,事情變得很奇怪。說readFromSocket後

,螺紋-1有要求X與和線程2具有請求Y.但是這裏面的processRequest(),線程1開始處理請求Y.

+0

請學習如何使用線程池。 – Snickers3192

+0

已經降低了投票的人,請你澄清downvote的原因嗎? – Anit

回答

1

有你的代碼的各種問題。

正如你自己想的那樣,一個線程P產生一些可能被消耗的東西,或者在P產生一個新結果之前沒有被另一個線程消耗是不理想的。

因此,簡單地存儲像你這樣的價值是不好的做法。合理的答案是:使用設計的數據結構以允許「一個線程放入某個東西,其他線程放出東西」;像ArrayBlockingQueue

然後:這是一個巨大的浪費時間爲一個工作創建一個線程,然後把它扔掉。

取而代之:創建一個ExecutorService,並將任務轉換爲該服務。該服務可以基於線程的,重新使用;而不是扔掉。

3

這裏的問題是,「請求」可能會在新線程開始處理它之前被修改。

這不是Java語言所允許的。

您不必擔心request在被新線程處理之前被修改。因爲,Thread.start()建立發生之間的關係request變量和processRequest(request)方法調用在新線程之間的關係。

當一個語句調用Thread.start時,與該語句具有happen-before關係的每個語句與新線程執行的每個語句之間都有一個happen-before關係。新線程可以看到導致創建新線程的代碼的影響。

因此,此聲明String request = readFromSocket(socket);發生在new Thread(...).start();之前以及新線程執行的任何代碼。

另外String是不可變的,所以它一旦創建就不會改變。你很安全。

這就是說。您最好使用線程池來處理請求。

ExecutorService executorService = Executors.newFixedThreadPool(100); 

while (true) { 
    String request = readFromSocket(socket); 
    Runnable task =() -> { 
     processRequest(request); 
    }; 
    executorService.submit(task); 
} 

同樣,調用ExecutorService.submit創建之前,無論發生什麼情況,並在任務中的任何語句之間的之前發生關係。

+0

在我的方案中,請求將是一個文件名。您可以根據目錄的大小獲取多個請求。當我在一個文件較少的目錄上嘗試我的代碼時,一切都很好。但是當我用一個有數千個文件的目錄運行我的代碼時,事情變得很奇怪。 在readFromSocket之後說,Thread-1有請求X並且Thread-2有請求Y.但是在processRequest()中,Thread-1開始處理請求Y. – Anit

+0

我編輯了我的代碼和我的問題。你能看一下嗎?謝謝! – Anit