[英]how to process real time data with executor service?
我的目標是使用ScheduledExecutorService
收集實時數據,每 5 秒掃描一次數據庫,捕獲任何新數據點,然后進行一些計算。 數據在不確定的時間內到達數據庫(即 2 秒內 3 個數據點或 2 秒內 5 個數據點)
對於每一個傳入的數據點,計算時間要求為 10 秒。 我的問題是:如何在不干擾計算方面的同時更新我的捕獲數據堆棧。 我也認為:
ScheduledExecutorService
,因為計算時間比掃描對應的時間長。有什么我可以參考的實現嗎? 我沒有主意,我沒有樣本,而是偽格式。 我嘗試可怕地使用 while-loop,然后通過 pid 進程將其殺死,摘錄如下:
//how to process real time data
while(true) {
if(calculationBegins) { //when first data point arrives
while(true) {
int oldDataSize = RealTimeData.size();
for(int i = 0; i < oldDataSize; i++) {
//
//complex calculation that takes 10 sec
//
}
//if new data arrived, break out and proceed calculation
while(true){
if(RealTimeData.size() > oldDataSize) break; //ScheduledExecutor will update the new size
}
}
}
}
這是完整的代碼(兩個文件)
package test;
import static test.HikariCPDataSource.calculationBegins;
import static test.HikariCPDataSource.RealTimeData;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
static List<String> capture = new ArrayList<String>();
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
Runnable extract = () -> {
HikariCPDataSource.getData(args[0]);
};
service.scheduleAtFixedRate(extract, 0, 5, TimeUnit.SECONDS);
//how to process real time data
while(true) {
if(calculationBegins) {
while(true) {
int oldDataSize = RealTimeData.size();
for(int i = 0; i < oldDataSize; i++) {
//
//complex calculation that takes 10 sec
//
}
//if new data arrived, break out and proceed calculation
while(true){
if(RealTimeData.size() > oldDataSize) break;
}
}
}
}
}
}
package test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
public class HikariCPDataSource {
private static HikariConfig config = new HikariConfig();
private static HikariDataSource ds;
public static boolean calculationBegins = false; //true: start calculation when the very first data points arrives
public static List<String> RealTimeData = new ArrayList<>(); //capture real time data from database
public static int index = 0;
static {
config.setJdbcUrl("jdbc:mysql://127.0.0.1/testdb");
config.setUsername("root");
config.setPassword("caspo123");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.setMaximumPoolSize(2);
config.setMinimumIdle(1);
config.setIdleTimeout(0);
config.setMaxLifetime(0);
ds = new HikariDataSource(config);
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
private HikariCPDataSource(){}
public static void setCalculationBegins() {
calculationBegins = true;
}
public static int getSizeHikariScout(){
return(RealTimeData.size());
}
public static int getIndex() {
return(index);
}
public static void resetIndex(int updateIndex) {
index = index + updateIndex;
}
public static void getData(String input1) {
Connection con = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
String output = null;
try{
con = ds.getConnection();
pstmt = con.prepareStatement("SELECT column1, column2 FROM testdb where id = ? and index > ?");
pstmt.setString(1, input1);
pstmt.setInt(1, getIndex());
resultSet = pstmt.executeQuery();
int indexCount = 0;
while (resultSet.next()){
if(!calculationBegins) setCalculationBegins();
output = String.join(",", resultSet.getString("column1"), resultSet.getString("column2"));
RealTimeData.add(output);
indexCount = indexCount + 1;
}
resetIndex(indexCount);
} catch (SQLException e){
e.printStackTrace();
} finally {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
我在這里看到的一種解決方案(實際上我自己也做過類似的事情)是創建兩個ExecutorService
。 一個是ScheduledExecutorService
,第二個是常規的FixedThreadPool
Executor。
第一個將定期運行,假設每 3 秒運行一次。 它只會掃描數據庫中的新數據點,如果找到一些,它會將任務提交/排隊到另一個執行器。
第二個 Executor 將執行所有計算以及您想要對數據執行的任何其他操作。 提交的任務將排隊等待執行,一旦有空閑線程就會完成。
這樣,所有線程管理和任務隊列處理都由 Executors 完成,您不必自己擔心。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.