java - 长时间运行的多线程应用程序部署到 tomcat 时比从命令行运行时慢 4 倍

标签 java multithreading tomcat

当我从命令行运行这个长时间运行的进程时,大约需要 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/

相关文章:

java - 如何在java中获取我的机器的IP地址?

java - Microsoft Graph API 在订阅请求时给出 InternalServerError

java - 自动提交关闭时 SQL JDBC java 提交

java - Spring MVC 中带有抽象类的 @ModelAttribute

python tqdm 多个进度条

c - 在 Linux 上用 C 处理多线程 TCP 服务器的最佳方法

c# - 用于串口数据处理的线程抛出 "This BackgroundWorker is currently busy and cannot run multiple tasks concurrently"

Tomcat 服务器上的 Java Servlet(找不到文件错误)

java - 使用 Tomcat 流媒体

java - 通过java运行批处理文件(.bat)所需的解决方案