问题陈述:
我有一个5000 ID指向数据库中的行。[可能超过5000]
每个Runnable在给定ID的情况下检索数据库中的行,并执行一些耗时的任务
public class BORunnable implements Callable<Properties>{
public BORunnable(String branchID) {
this.branchID=branchID;
}
public setBranchId(String branchID){
this.branchID=branchID;
}
public Properties call(){
//Get the branchID
//Do some time consuming tasks. Merely takes 1 sec to complete
return propObj;
}
}
我将这些可运行对象提交给执行者服务。
为此,我需要创建并提交5000甚至更多可运行对象到executor服务。在我的环境中,这种可运行对象的创建可能会导致内存不足异常。
[假设5000只是一个例子]
因此,我想出了一种方法,如果您提供其他不同的方法,我将不胜感激:
创建了固定大小为10的线程池。
int corePoolSize = 10;
ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize,
corePoolSize + 5, 10, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
Collection<Future<Properties>> futuresCollection =
new LinkedList<Future<Properties>>();
将所有branchID添加到branchIdQueue
Queue<String> branchIdQueue = new LinkedList<String>();
Collections.addAll(branchIdQueue, branchIDs);
我试图重用可运行的。创建了一堆可运行的
现在我希望将此数量的元素出队并为每个元素创建可运行
int noOfElementsToDequeue = Math.min(corePoolSize, branchIdQueue.size());
ArrayList<BORunnable>runnablesList = dequeueAndSubmitRunnable(
branchIdQueue,noOfElementsToDequeue);
ArrayList<BORunnable> dequeueAndSubmitRunnable(branchIdQueue,
noOFElementsToDequeue){
ArrayList<BORunnable> runnablesList= new ArrayList<BORunnable>();
for (int i = 0; i < noOfElementsToDequeue; i++) {
//Create this number of runnables
runnablesList.add(new BORunnable(branchIdQueue.remove()));
}
return runnablesList;
}
将检索到的可运行对象提交给执行者
for(BORunnable boRunnableObj:runnablesList){
futuresCollection.add(executor.submit(boRunnableObj));
}
如果队列为空,则创建所需的可运行对象。如果不是,我想重用可运行对象并提交给执行者。
在这里,我得到可重用的可运行对象的数量=总计数-当前活动计数
[对我来说足够了]
int coreSize=executor.getCorePoolSize();
while(!branchIdQueue.isEmpty()){
//Total size - current active count
int runnablesToBeReused=coreSize-executor.getActiveCount();
if(runnablesToBeReused!=0){
ArrayList<String> branchIDsTobeReset = removeElementsFromQueue(
branchIdQueue,runnablesToBeReused);
ArrayList<BORunnable> boRunnableToBeReusedList =
getBORunnableToBeReused(boRunnableList,runnablesToBeReused);
for(BORunnable aRunnable:boRunnableList){
//aRunnable.set(branchIDSTobeRest.get(0));
}
}
}
我的问题是
我无法找出线程池已释放了哪个Runnable,因此我可以使用它来提交
因此,我随机抽取了几个可运行对象并尝试设置branchId,但是随后可能发生线程竞争问题。 [不想使用挥发物]
最佳答案
重用Runnable
没有意义,因为问题不在于创建或释放可运行实例的成本。这些在Java中几乎是免费提供的。
您要做的是限制易于实现的待处理作业的数量:只需限制要传递给执行者服务的队列。就像将int
值(限制)传递给LinkedBlockingQueue
’s constructor一样简单。请注意,您也可以使用ArrayBlockingQueue
,因为LinkedBlockingQueue
不能为有限队列使用提供优势。
在为队列提供限制后,执行者将拒绝排队新作业。剩下要做的唯一事情就是为执行者提供适当的RejectedExecutionHandler
。例如。 CallerRunsPolicy
足以避免在线程都繁忙且队列已满时调用方创建更多新作业。
执行后,Runnable
受到垃圾回收。