2017-05-04 13 views
1

我是新來的併發網絡編程。Java併發性:如何同時從幾千個TCP套接字中同步檢索數據?

我的全球任務:開發java應用程序,它將每隔10秒從3000個tcp網絡設備同步檢索溫度。

檢索溫度過程/步驟:

  • 連接到通過TCP套接字特定的IP地址(3秒鐘超時)
  • 寫入登錄/密碼到插座
  • 從插座
  • 關閉連接
  • 讀出溫度

從一臺設備檢索溫度大約需要300-400ms。 檢索摘要時間是400ms * 3000 = 120秒

需要我爲每個任務啓動3000個線程來同時檢索或使用隊列和線程池?

是否存在其他想法?

請把我放到正確的方向。

+2

如果你是「新」這兩個概念,這是不是你應該工作。您需要從每個傳感器的基礎知識開始,然後將它們組合在一起 – CraigR8806

+0

您對每個傳感器/設備的溫度做什麼? – LoganMzz

+0

把它放到共享陣列和檢索完成的(所有設備)之後將陣列插入到PostgreSQL數據庫 – Dmitry

回答

2

您可以使用Java API它,Java提供ScheduledThreadPoolExecutor這將讓你:

  • 創建線程池(併爲您提供多少個線程要你控制在JVM中用於此目的, JVM管理該線程池)。
  • 公開方法來指定任務的時間表。

我爲您提供了一個示例實現,我添加了代碼註釋以便您理解,您還可以參考聯機文檔或示例。如有任何問題,請隨時通知我。

順便說一句,如果你想獲得結果從線程的執行當時不是使用Runnable可以使用Callable接口,它可以讓你返回的東西,和ScheduledThreadPoolExecutor重載了它讓你通過一個Callable對象方法。

示例代碼:

import java.util.concurrent.ScheduledThreadPoolExecutor; 
import java.util.concurrent.TimeUnit; 

public class ScheduledThreadPoolExecutorExample { 

    private final static int MAX_NUMBER_OF_THREADS = 2; 
    private final static int EXECUTION_SCHEDULE_PERIOD_IN_SECONDS = 5; 
    private final static int INITAL_DELAY_IN_SECONDS = 0; 

    // set maximum number of threads as per your requirement/performance tuning, for testing set it to "2" and to have better feel. 
    private final static ScheduledThreadPoolExecutor SCHEDULED_THREAD_POOL_EXECUTOR = new ScheduledThreadPoolExecutor(MAX_NUMBER_OF_THREADS); 

    public static void main(String[] args) { 
     scheduleTask(new MyRunnableTask("google1.com", 80)); // if you want more fields to set then either use constructor or have setter methods. 
     scheduleTask(new MyRunnableTask("google2.com", 80)); // if you want more fields to set then either use constructor or have setter methods. 
     scheduleTask(new MyRunnableTask("google3.com", 80)); // if you want more fields to set then either use constructor or have setter methods. 
     scheduleTask(new MyRunnableTask("google4.com", 80)); // if you want more fields to set then either use constructor or have setter methods. 
    } 

    private static void scheduleTask(Runnable runnable) { 
     SCHEDULED_THREAD_POOL_EXECUTOR.scheduleAtFixedRate(runnable, INITAL_DELAY_IN_SECONDS, EXECUTION_SCHEDULE_PERIOD_IN_SECONDS, TimeUnit.SECONDS); 
    } 
} 

的Runnable:

import java.util.Date; 

public class MyRunnableTask implements Runnable { 

    private String hostName; 
    private int port; 

    MyRunnableTask(String _hostName, int _port){ 
     this.hostName = _hostName; 
     this.port = _port; 
    } 

    @Override 
    public void run() { 
     System.out.println(this.hostName + ":: I am getting executed: " + this.hashCode() + " | " + Thread.currentThread().getId() + " | " + new Date()); 

     // implement your socket programming code here 

     try { 
      Thread.sleep(500); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

} 
1

您不需要啓動3000個線程。只需啓動12個主題 - 也許多一些提供一些保證金 - 並分配他們之間的設備。當然,您需要確保您運行的機器具有必要的資源。

如果您打開套接字,您可能可以在單個線程中完成此操作,具體取決於實際讀取數據的400ms數量以及協議是否允許每次登錄多次讀取。這將允許你在只學習網絡編程的同時完成工作,這比在單個項目上學習網絡編程和多線程編程要容易得多。

0

最簡單的方法:

請注意,當您使用get result時,子任務可能會引發異常。

注:這是一個簡單的解決方案(容易實現,其工作的大部分時間,但比較有限,可能是你的情況較少高性能)。

可以使用異步API的實現更好的解決方案。看看AsynchronousSocketChannel用於基於未來的承諾/ API或Reactor Netty一個更被動的做法。

1

如果你的任務就是給每個設備每隔10秒,但實際開始時間並不重要(比如某些設備是在0連接連接:0:0秒,然後0:0:10,0:0:20​​,其他如0:0:1,0:0:11等設備),那麼你可以使用12個線程,正如Warren Dew所建議的。如果所有設備必須同時被嚴格調用,那麼您必須浪費3千兆字節用於3000個線程,或者使用NIO(例如Netty庫或AsynchronousSocketChannel)。使用NIO不可靠 - 從編程的角度來看都易出錯,並且標準庫的實現可能存在錯誤。

相關問題