ThreadPoolExecutor正在运行的应用程序
账单类具有与国家明智账单相关的所有逻辑。它从数据库中获取结果,然后为用户开票。帐单类实现Runnable。我想根据国家参数并行执行结算,以便大量用户(500万+)非常快速地结算。现在需要数小时完成。ThreadPoolExecutor正在运行的应用程序
我想实现ThreadPoolExecutor执行Billing类,但很困惑如何?以下有什么区别或者我做错了什么?请建议!区共有20个国家,但我在这里粘贴仅5
//for 20 countries ThreadPoolExecutor (20,20,20.......)????
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
executor.execute(new Billing("UK"));
executor.execute(new Billing("USA"));
executor.execute(new Billing("Germany"));
executor.execute(new Billing("Spain"));
executor.execute(new Billing("Italy"));
OR
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
for(int i=0;i<5;i++) // for 20 countries i<20??
{
executor.execute(new Billing("UK"));
executor.execute(new Billing("USA"));
executor.execute(new Billing("Germany"));
executor.execute(new Billing("Spain"));
executor.execute(new Billing("Italy"));
}
while (! executor.isTerminated()) {
try{
executor.awaitTermination(100, TimeUnit.SECONDS);
}catch(InterruptedException iE)
{
iE.printStackTrace();
System.out.println("Executor Exception: "+ iE);
}
在此先感谢!
循环解决方案看起来不正确。不需要多次执行相同的Runnable
。
你既corePoolSize
和maximumPoolSize
设置为5
,这意味着执行程序将保持线程的数量在游泳池5
,即使它们是空闲实例ThreadPoolExecutor
。它还说池中的线程数不能超过5
。
在此位置,您可以预计至多5
线程正在并行执行任务(Billing
对象)。
随着您继续提交Billing
对象到executor
与execute
方法它们被添加到您提供的ArrayBlockingQueue
。此队列的大小为10
。在某些情况下,队列中的队列可能已经处于最大容量并且不能承担更多任务,在这种情况下,任务将被拒绝并提供给ThreadPoolExecutor
构造函数中提供的RejectedExecutionHandler
。它的工作是用已实施的方法rejectedExecution
处理被拒绝的任务。
如果你想找到是否有任何被拒绝的任务,你必须提供自己的RejectedExecutionHandler
而不是使用默认的ThreadPoolExecutor.CallerRunsPolicy
。你可以像这样做:
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5,
TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(10),
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r,
ThreadPoolExecutor executor) {
System.out.println("I got rejected: " + r);
if (!executor.isShutdown()) {
r.run();
}
}
});
@NishantShresthth ..当我尝试执行(NewBilling(“国家”))一些帐单类并没有执行..例如20只有16只正在运行... – 2013-02-27 16:30:30
或者我误认为声明ThreadPoolExecutor只有ArrayBlockingQueue
如果您的“结算”任务非常耗时,如果队列在某些情况下已满,则某些任务可能会被拒绝。在这种情况下,增加队列的大小应该会有所帮助。 – 2013-02-27 17:09:21
我不确定你了解循环如何工作。不同之处在于第二个代码块将在每个列出的国家/地区运行计费5次。
但不使用for循环.. Threadpoolexecutor没有执行所有20 Billings? – 2013-02-27 16:32:03
假设你正在谈论的代码for
环部分并不明显,将如何工作。
理想的循环将是这个样子:
for(String country : countryCollection) {
executor.execute(new Billing(country));
}
你有没有考虑使用enum
?
static class Billing implements Runnable {
enum Country {
UK,
USA,
Germany,
Spain,
Italy;
}
public Billing(Country country) {
}
@Override
public void run() {
}
}
public void test() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(10),
new ThreadPoolExecutor.CallerRunsPolicy());
for (Billing.Country country : Billing.Country.values()) {
executor.execute(new Billing(country));
}
}
第一:忘记循环
for(int i=0;i<5;i++) // for 20 countries i<20??
{
executor.execute(new Billing("UK"));
executor.execute(new Billing("USA"));
executor.execute(new Billing("Germany"));
executor.execute(new Billing("Spain"));
executor.execute(new Billing("Italy"));
}
这一切账单多次遍历。
做的正确的事情是在第一个片段:
executor.execute(new Billing("UK"));
executor.execute(new Billing("USA"));
executor.execute(new Billing("Germany"));
executor.execute(new Billing("Spain"));
executor.execute(new Billing("Italy"));
另一个错误在于对终端的检查:
while (! executor.isTerminated()) {
try{
executor.awaitTermination(100, TimeUnit.SECONDS);
}catch(InterruptedException iE)
{
iE.printStackTrace();
System.out.println("Executor Exception: "+ iE);
}
}
的Executor.awaitTermination
的Javadoc说:
块直到所有任务在关闭请求后完成执行,
但您永远不会发出关闭请求。
在你的情况,你可以充分利用ExecutorCompletionService
为:
CompletionService<String> ecs = new ExecutorCompletionService<String>(executor);
List<String> countries= Arrays.asList("UK","USA","Germany","Spain","Italy");
for(String country : countries) {
ecs.submit(new Billing(country),country);
}
// wait for completion
for(int i=0;i<countries.size();i++){
ecs.take(); // wait for next country completion
}
// all work completed, shutdown
executor.shutdownNow();
+1,但你永远不会发出关机请求。 – 2013-02-27 17:13:38
另一种方式来思考实现这个就是看看The Fork/Join Framework。这看起来似乎可以真正从炼钢获益。例如,你可以看起来相当干净地分解它。这基本上可以让您打破用户或部分用户的计费任务,而不是让一个看起来代表一个国家的线程在整个计费过程中工作。
我在Java 6上运行.. fork/join在java 7上? – 2013-02-27 20:26:07
图书馆已经有一段时间了,我编辑了我的回复以提供链接 – 2013-02-27 20:27:20
你只是询问是否要使用'for'循环?你的意思并不完全清楚。 – 2013-02-27 16:17:47
@TimBender ...........我修改了我的问题... – 2013-02-27 16:25:58
@TimBender ..我很困惑在实施ThreadPoolExecutor执行Billing类..我该如何实现?我是否必须在ThreadPoolExecutor中使用For循环?或者它将并行运行所有计费类.. – 2013-02-27 16:28:23