问题陈述:
我有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;
}
}
我打算将这些runnable提交给执行者服务。
为此,我需要为执行程序服务创建并提交5000个甚至更多的runnable。在我的环境中创建runnable可能会抛出内存异常。 [鉴于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);
我正在尝试重用runnable。创建了一堆可运行的
现在我想要将这些元素出列并为每个
创建runnableint 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;
}
将检索到的runnables提交给执行者
for(BORunnable boRunnableObj:runnablesList){
futuresCollection.add(executor.submit(boRunnableObj));
}
如果队列为空,我创建了我需要的runnables。如果不是,我想重用runnable并提交给执行者。
在这里,我获得了要重用的可运行数量=总计数 - 当前活动计数 [近似对我来说足够了]
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,所以我可以使用它来提交
因此,我随机取几个runnable并尝试设置branchId,但随后可能会发生线程争用问题。 [不想使用volatile]
答案 0 :(得分:1)
重用Runnable
毫无意义,因为问题不在于创建或释放可运行实例的成本。这些在Java中几乎是免费的。
您要做的是限制易于实现的待处理作业数:只需向传递给执行程序服务的队列提供限制 。这就像将int
值(限制)传递给LinkedBlockingQueue
’s constructor一样简单。请注意,您也可以使用ArrayBlockingQueue
,因为LinkedBlockingQueue
不会为有界队列使用提供优势。
当您为队列提供限制时,执行程序将拒绝排队新作业。剩下要做的唯一事情就是向执行者提供适当的RejectedExecutionHandler
。例如。 CallerRunsPolicy
足以避免调用者在线程全部忙且队列已满时创建更多新作业。
执行后,Runnable
将进行垃圾回收。