当我从命令行运行这个长时间运行的进程时,大约需要 30 秒才能完成。当我将相同的代码部署到 tomcat7 并从一个简单的 Vaadin Web 应用程序调用相同的函数时,它需要将近 150 秒。这是执行特定功能的时间,与减慢它的界面无关。
这是一个说明问题的简单示例:
public static void main(String[] args) {
try {
multiCounter(800);
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}
System.out.println("Completed");
}
public static void multiCounter(int numberOfCounters) throws InterruptedException, ExecutionException
{
//estimate the number of available processors
int maxNumberOfThreads = Runtime.getRuntime().availableProcessors();
//create thread pool and queue for future jobs
ExecutorService pool = Executors.newFixedThreadPool(maxNumberOfThreads);
ArrayList<Future<Integer>> futureJobs = new ArrayList<Future <Integer>>();
for(int index=0; index<numberOfCounters; index++)
{
Callable<Integer> callable = new dummyCalculator();
Future<Integer> future = pool.submit(callable);
futureJobs.add(future);
}
//placeholder for results
ArrayList <Integer> results= new ArrayList <Integer>(0);
//pull completed jobs from queue and extract results,
//adding to results container
for(Future<Integer> future : futureJobs)
{results.add(future.get());}
for(Integer res : results)
{System.out.println("Count:" + res);}
//close thread pool
pool.shutdown();
}
final static class dummyCalculator implements Callable<Integer>
{
@Override
public Integer call() throws Exception {
Integer counter = 0;
for(int p1Index=0; p1Index<800; p1Index++)
{
for(int p2Index=p1Index; p2Index<800; p2Index++)
{
for(int markerIndex=0; markerIndex<200; markerIndex++)
{counter++;}
}
}
return(counter);
}
}
我运行它的服务器有 48 个可用内核。当我从命令行运行此代码时,我得到 48 个线程,每个线程运行 ~98%。根据 top,当我通过 tomcat 运行它时,每个线程的最高使用率约为 82-86%。如果我减少 tomcat 代码中的线程数,则每个线程的百分比会增加。 12 个线程将使我获得每个线程 92% 的效率。 1 个线程 99%...
tomcat 是否以某种方式限制了这个线程池,或者有一些我不知道的额外线程开销?或者在这种情况下有更好的多线程方法吗?一些开销显然是可以接受的,但是这里似乎有些东西不适合通过 tomcat 花费更长的时间。
最佳答案
您是否尝试过确保 Tomcat 和您的作业使用的线程总数等于您系统上的核心数?我敢说,这些线程的执行率可能会接近 99%。
我的另一个问题是 Tomcat 线程的优先级是否高于工作线程。如果是这种情况,那么您应该在一致的基础上看到这种差异。我不记得你是否可以使用 jconsole 或 visualvm 查看线程优先级,但也许增加线程池的线程优先级应该提供更多的 cpu 周期,但这会影响 tomcat 处理 Web 请求的能力。
关于java - 长时间运行的多线程应用程序部署到 tomcat 时比从命令行运行时慢 4 倍,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27554340/