在系统上工作以并行支持多个数据库查询。考虑到要从每个数据中查询的数据很多,要求是将每个数据库查询与其他数据库查询分开。意思是,一个数据库/表上的加载不应该对其他表查询产生影响。我使用ExecutorService在Java中开发了一个解决方案。每个数据库使用一个ExecutorService(固定大小,1个线程)。我维护一个DB名称TO ExecutorService的映射,并在接收查询请求时将调用指向相应的执行程序服务。考虑到可以并行查询一百个数据库,不确定ExecutorService是否是正确的选择......!我做了一些评估,初步结果看起来还不错。我对这个解决方案的一个挑战是,当我动态创建ExecutorServices时,我很难在应用程序停止时优雅地关闭它们。
解决此问题的其他方法是维护全局(意味着跨所有数据库)查询工作线程池,并随机重用它们以用于传入请求。但是,这并不能保证所有数据库查询都具有相同的优先级。
DatasetFactory.java
public class DataSetExecutorFactory {
private static Map<String, DataSetExecutor> executorMap = Collections.synchronizedMap(new HashMap<String, DataSetExecutor>());
public static DataSetExecutor getDataSetExecutor(String dbName){
DataSetExecutor executor = null;
executor = executorMap.get(dbName);
if(executor == null){
executor = new DataSetExecutor(dbName);
executorMap.put(dbName, executor);
}
return executor;
}
}
}
DataSetExecutor.java
public class DataSetExecutor {
private ExecutorService executor = Executors.newFixedThreadPool(1);
public List<Map<String, Object>> execQuery(String collecName, Map<String, Object> queryParams){
//Construct Query job.
//QueryWorker extends 'Callable' and does the actual query to DB
QueryWorker queryWorker = new QueryWorker(Map queryParams);
Future<QueryResult> result = null;
try{
result = executor.submit(queryWorker);
}catch (Exception e){
//Catch Exception here
e.printStackTrace();
}
}
答案 0 :(得分:0)
我认为你误解了ExecutorService的工作原理。您应该将单个ExecutorService设置为大小为n的FixedThreadPool(n =数据库数量或最大并行查询数量),而不是为每个数据库创建ExecutorService。线程池将为您执行并行处理工作。您只需跟踪数据库名称作为QueryWorker的一部分,该名称将提交给ExecutorService。
这也使得关闭变得容易,因为ThreadPool会自动清理未使用的线程,你只需要在应用程序关闭时关闭它。
尽管如此,由于所有这些并行处理都发生在同一个JVM和同一台机器上,因此您可能会遇到内存或CPU限制,具体取决于查询的强度。