java服务器中的执行程序池

时间:2014-07-09 14:51:45

标签: java multithreading tomcat executorservice

我有一个java服务器正在处理客户请求的网页中的图像。

现在处理这些图像需要时间和内存,并且进入处理图像的n个线程会挂起服务器。

现在为了避免处理图像的代码,我将它们放在Runnable类中并从执行程序池中调用它们。

我的问题是,以下实现是否是在服务器中执行Executor池的正确方法。

Runnable类是 -

public class MyRunnable implements Runnable {
     private final String id;

    MyRunnable(String tid) {
        this.id = tid;
    }

    @Override
    public void run() {
        NewAlbumImage nai = new NewAlbumImage();                
        nai.save_image(id,false);        
    }
} 

运行Runnable类的代码如下 -

newa.NewClass newca = new newa.NewClass();
Runnable mr = new MyRunnable(id);
newca.executor.execute(mr);

NewClass类有一个静态执行器变量 -

static ExecutorService executor;

我在Web应用程序启动时初始化执行程序变量并在Web应用程序关闭时销毁它 -

public class AppNameServletContextListener implements ServletContextListener {

@Override
public void contextInitialized(ServletContextEvent sce) {
    System.out.println("Initializing Executor Pool");
    NewClass nc = new NewClass();
    nc.executor = Executors.newFixedThreadPool(10);


}

@Override
public void contextDestroyed(ServletContextEvent sce) {
    NewClass nc = new NewClass();
    nc.executor.shutdown();
    try {
        nc.executor.awaitTermination( 10L, TimeUnit.MINUTES);
    } catch (InterruptedException ex) {
        System.out.println("Executor Pool await Termination exception");
    }
}   
}

2 个答案:

答案 0 :(得分:0)

你提到了

  

类NewClass有一个静态执行器变量 -   static ExecutorService executor;

我建议使用

NewClass.executor.execute(yourRunnableInstance);

NewClass.executor.shutdown();

很容易理解executor是一个静态字段,您不需要创建多个NewClass个实例。

其余的代码看起来很好。

答案 1 :(得分:0)

我会考虑一些事情。

首先,您的执行者是静态的。我会使用某种依赖注入框架在需要的地方正确地注入执行程序。或者将它作为属性添加到servlet上下文中,并在servlet初始化时自己注入。

使用ServletContext创建/关闭:

@Override
public void contextInitialized(ServletContextEvent sce) {
    ServletContext context = sce.getServletContext();
    context.setAttribute("executor", Executors.newCachedThreadPool());
}

@Override
public void contextDestroyed(ServletContextEvent sce) {
    ServletContext context = sce.getServletContext();
    ExecutorService executor = (ExecutorService)context.getAttribute("executor");
    executor.shutdown();
}   

其次,您正在使用固定的线程池。这是一个可能的瓶颈(但也许是故意保存CPU?)。如果没有办法同时调整10张图片的大小,你就可以了。但是,如果处理它们的速率低于请求进入的速率,您将发现固定的线程池不起作用。实际上,如果您的应用程序将响应的调整大小任务加入到用户,则您已将任何给定时刻的可能请求数限制为已定义的线程数。尝试使用缓存的线程池。线程是按需创建的,并且会因不活动而死亡。

Executors.newCachedThreadPool();

最后,我认为这更重要,你的应用程序如何扩展?您拥有的用户越多,您在Web服务器上处理的图像就越多。您的响应时间会很快降低。尝试同时调整图像大小的三个用户可以使用100%的CPU。我建议你把你的图像调整到另一台机器,一个更有能力。