Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于并行处理的Java执行器服务_Java_Concurrency - Fatal编程技术网

用于并行处理的Java执行器服务

用于并行处理的Java执行器服务,java,concurrency,Java,Concurrency,在一个系统上工作以并行支持多个数据库查询。考虑到每个数据库都有大量数据需要查询,因此需要将每个数据库查询与其他数据库查询分开。也就是说,一个数据库/表上的负载不应该对其他表查询产生影响。我使用ExecutorService用Java开发了一个解决方案。每个数据库使用一个ExecutorService(固定大小,1个线程)。我维护数据库名到ExecutorService的映射,并在收到查询请求时将调用定向到相应的executor服务。考虑到可以并行查询100个数据库,不确定ExecutorServ

在一个系统上工作以并行支持多个数据库查询。考虑到每个数据库都有大量数据需要查询,因此需要将每个数据库查询与其他数据库查询分开。也就是说,一个数据库/表上的负载不应该对其他表查询产生影响。我使用ExecutorService用Java开发了一个解决方案。每个数据库使用一个ExecutorService(固定大小,1个线程)。我维护数据库名到ExecutorService的映射,并在收到查询请求时将调用定向到相应的executor服务。考虑到可以并行查询100个数据库,不确定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;
        }
    }
}
公共类DataSetExecutorFactory{
私有静态映射executomap=Collections.synchronizedMap(新的HashMap());
公共静态DataSetExecutor getDataSetExecutor(字符串dbName){
DataSetExecutor executor=null;
executor=executomap.get(dbName);
if(executor==null){
executor=新的DataSetExecutor(dbName);
executorMap.put(数据库名,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();
        }
    }
公共类数据采集器{
私有ExecutorService executor=Executors.newFixedThreadPool(1);
公共列表执行查询(字符串collecName,映射查询参数){
//构造查询作业。
//QueryWorker扩展了“Callable”,并对DB执行实际查询
QueryWorker QueryWorker=新的QueryWorker(映射queryParams);
未来结果=空;
试一试{
结果=执行者提交(查询工);
}捕获(例外e){
//在此捕获异常
e、 printStackTrace();
}
}

我认为您误解了ExecutorService的工作原理。与其为每个数据库创建ExecutorService,不如将单个ExecutorService作为大小为n的固定线程池(n=#个数据库或#个最大并行查询)。线程池将为您执行并行处理工作。您只需在将提交给ExecutorService的QueryWorker中跟踪数据库名称

这也使得关闭更容易,因为线程池将自动清理未使用的线程,并且在应用程序关闭时只需关闭一次


尽管如此,由于所有这些并行处理都发生在同一个JVM和同一台机器上,您可能会遇到内存或CPU限制,这取决于您的查询强度。

您的问题是什么?我认为这是一个有效的解决方案,尽管如果您将所有查询都推上,您的查询不会以
并行方式运行到单线程执行器服务。为什么每个数据库都有一个执行器而不是一个执行器(池中有多个线程)哪个处理任何queryWorker?将数据源传递给queryWorker,让其创建连接。@PatrickMevzek是否有其他或更好的方法来实现此用例?@SamOrozco是的,我发现在每个数据库的执行器服务中按顺序执行查询。感谢您的响应。原因,我更喜欢DB-->执行器服务是通过DB隔离流量。请求队列可能会被一个DB的查询填满,并且不希望这影响其他DB查询的查询响应时间。内存/CPU限制方面的要点可以解释这一点。