【发布时间】:2014-10-20 16:15:42
【问题描述】:
问题陈述:
我有 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 个甚至更多的可运行文件并将其提交给执行器服务。在我的环境中创建可运行文件可能会引发内存不足异常。 [鉴于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。创建了一堆runnable
现在我希望这个数量的元素被出列并为每个元素创建可运行的
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; } -
将检索到的runnables提交给执行器
for(BORunnable boRunnableObj:runnablesList){ futuresCollection.add(executor.submit(boRunnableObj)); } 如果队列为空,我创建了所需的可运行文件。如果不是,我想重用runnable并提交给executor。
-
在这里,我得到要重用的可运行的数量 = 总计数 - 当前活动计数 [对我来说大概就足够了]
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,因此我可以使用它来提交
因此,我随机取了几个 runnables 并尝试设置 branchId,但随后可能会出现线程竞争问题。 [不想使用 volatile]
【问题讨论】:
-
为什么不直接使用branchidQueue,提交的时候直接创建BORunnable呢?我不明白你为什么需要
runnablesList。所以你会保存那段记忆。 -
试图避免 BORunnable 中的迭代。如果可运行对象中有迭代,那么多线程概念就没有用处了。
-
为什么不使用 Future.isDone()? docs.oracle.com/javase/7/docs/api/java/util/concurrent/…
-
No 不是 inside 可运行文件。我的意思是
for(String id:branchidQueue){ futuresCollection.add(executor.submit(new BORunnable(id))); }好吧,只是用 dequeing,但你知道我的意思。只是省略了 ArrayList - 步骤。 -
@Fildor 创建 BoRunnable 可能会导致 JVM 环境内存不足异常。 BoRunnable 对象创建的数量没有指定限制。
标签: java multithreading threadpool runnable executorservice